3

我们有一个将 webapp 实现为多个OSGibundle 的场景。我们希望进行捆绑更新,以透明地将错误修复等部署到正在运行的系统。假设更新周期包含刷新和捆绑重新启动,当正在重新加载其类的对象已存储在 s 的HttpSession前导时,这将导致问题ClassCastException

我们正在研究几种不同的方法来使包更新成为可能,而不会丢失登录会话中的状态。为了简化会话状态访问依赖图,我们正在考虑设置以下限制:

  • 一个bundle只能访问它自己的会话状态,即不能直接访问另一个bundle设置的状态(强制调用bundle API来间接访问它的状态)
  • 添加到会话状态的对象的 Java 类应该来自包本身(以避免我们的会话状态受到除我们之外的其他包的更新的影响)这些限制实际上只有下面的一些替代方案需要。

因此,这些是我们以某种从最小到最大暗示顺序提出的替代方案:

  1. 将所有状态存储为java.*类型(String、、List等)
    -> 状态类永远不会重新加载。
  2. 将会话锁定到创建其状态的服务版本(通过 f ex 使用转发到该会话之前使用的版本的代理解决方案
    ) -> 新会话将获取更新的捆绑版本,而现有会话将保留在旧版本上。
  3. 更新捆绑包时序列化会话状态并将其反序列化回新的捆绑包版本(如 appserver 会话序列化,但在更细粒度的级别)
    -> 所有会话将获取更新的捆绑包,但要求序列化状态兼容。
  4. 只要有活动的会话,就避免更新有状态的服务,利用传统的负载均衡器技术一次更新一个应用服务器
    -> 更长的部署周转时间并且可能需要更多资源。
  5. 完全避免有状态OSGi服务并将状态保留在其他地方
    -> 不处理OSGi...

我错过了任何有趣的选择吗?
您推荐什么解决方案?

[虽然这篇文章明确讨论了会话状态,但同样的讨论可能适用于其他范围,例如会话状态、应用程序状态等]

4

1 回答 1

4

在我看来,正确的答案不是一个简单的规则,而是一组规则,例如:

  • 如有必要,仅在应用程序的入口点使用有状态对象。入口点可以是 Servlet、套接字侦听器、IO 设备的侦听器类(从外部向您的应用发送请求并需要状态的东西)...
  • 仅在会话中存储从来自 java.* 的类实例化的对象;(你的第一个选择。)
  • 如果您认为需要存储复杂的数据结构,请再想一想。您是否有更快地返回持久数据的动机?
  • 在会话中存储尽可能少的信息(没有实体对象,只有它们的 id)
  • 在服务包中使用缓存来加快响应时间。我建议使用支持集群和 XA 事务的键值对缓存实现。这两个要求在以后都可能很重要。在键中仅使用 java.* 类。在读取密集型数据使用的情况下(在 Web 应用程序的情况下占很大比例)使用失效缓存。

有关缓存和持久数据关系的更多信息:

  • 将您的持久数据划分为一组具有相同生命周期的逻辑集。
  • 一组逻辑数据只能从一个包中修改和缓存。如果您没有此规则,如果有人更改了一个包的代码(这会影响另一个包中的缓存),缓存可能会损坏。

这就是我们在我的公司设计 Web 应用程序的方式,这似乎是个好方法。但是,可以有其他方式。

于 2013-05-06T20:41:35.090 回答