2

我已经看到了这个问题的点点滴滴,但没有直接回答它。

这是假设的环境:

  • 20 个以 Java 为中心的服务器(即 Tomcat / Glassfish / Jboss / 其他)通过 HTTP 与客户端通信
  • 服务器前面的 HTTP 负载平衡器不能保证每次客户端连接都能将您带回同一台服务器。
  • 其他任何东西都是可用的技术明智。(JMS / Camel / Memcached / Hazelcast / 不管)

我们希望 Joe 和他的浏览器(可能使用 Flash 或 HTML5 或任何客户端技术)接收发布到所有 20 个服务器都可用的 JMS 主题的所有消息。

这是一个例子:

  • Joe 的第一个 HTTP 连接到达服务器 A
  • 服务器 A 现在有一个针对 Joe 的 HTTP 会话(通过 cookie 等)
  • 服务器 A 为他订阅主题(基于他的会话 ID 等)
  • Joe 的 HTTP 连接结束。
  • 一条消息发布到该主题。
  • Joe 建立另一个连接,但这次它由服务器 F 处理。

这对我来说有点模糊。

  • 我们知道 Joe 返回时的会话 ID(并且可能会话在所有服务器之间共享),但是 JMS 订阅呢?如果服务器 F 必须再次订阅 Joe 的主题,他只是错过了一条消息吗?A 是 Joe 可以从中检索该消息的唯一服务器,还是当他订阅 F 并且它只知道他没有收到消息时会发生某种魔术(大概在 A 上等待他)。

我想我有点不清楚“订阅”的作用(过程明智)以及它与集群服务器的关系。我正在使用长轮询(cometd)和 websockets 来帮助客户端在接收主题消息时响应,但是必须考虑当有许多服务器可以处理连接和订阅时这将如何工作。我想避免服务器固定。

感谢您的任何指示。

EDIT1:希望有所澄清。我在这里指的是 BlazeDS 框架中提供的特定内容。它允许 HTTP 客户端订阅 JMS 主题并使用长轮询来实现近乎实时的客户端更新,但它要求一旦客户端访问服务器,所有请求都必须返回到该服务器。因此,它必须(以某种方式?)保持该服务器上该客户端的主题订阅处于活动状态。我想摆脱这个要求(使用任何技术/框架)。

4

2 回答 2

4

JMS 服务器跟踪所做的每个订阅,并在持久订阅和非持久订阅之间产生差异。假设您有客户 A、B、C 和主题 T。

  1. Client A 订阅 Topic T 并等待消息
  2. 客户端 B 订阅主题 T 等待消息
  3. 客户端 C 对主题 T 进行持久订阅并等待消息
  4. 客户端 B 和 C 在将消息 M 放入主题 T 前几秒崩溃
  5. 客户端 A 获取消息 M 的副本,因为它已订阅并且当前连接到 jms 服务器
  6. 客户端B重启但没有得到消息的副本,因为消息到达主题时它没有连接到jms服务器
  7. 客户端 C 重新启动并获取消息 M,因为它提供了一个持久订阅,JMS 服务器保留了消息 M 的副本,而 C 崩溃并等待 C 回来并声明该消息。

消息服务器上有管理设置,用于控制 jms 服务器在将消息发送到死信队列之前等待持久订阅者返回并声明消息的时间长度或主题上的最大消息数等待订阅者回来并索取。您确实需要在永不丢失消息与流消息和内存或磁盘空间不足之间取得平衡。

请注意,持久队列的概念与持久订阅者的概念不同。持久队列和主题通过在确认收到消息之前将队列和消息的内容写入磁盘来保护您免受 JMS 服务器崩溃的影响。持久订阅者是关于当消息到达而客户端未连接时消息会发生什么。


老答案。

以您对 SQL 数据库的看法来考虑 JMS 服务器。从 Web 容器的角度来看,应该有一个到 JMS 服务器的连接池,所以你要做的是获取到 JMS 服务器的连接并订阅一个主题。例如。

  • JMS 服务器有一个名为 AddressChangeTopic 的主题
  • 每个 tomcat 实例都有一个对 AddressChangeTopic 的订阅
  • Joe / Jim / John ... 等的地址更改事件都转到相同的 AddressChangeTopic 而不是转到 JohnAddressTopic、JimAddressTopic 等。如果您有 1 个应用程序,为每个用户创建一个单独的主题是不切实际的百万用户 你会有一百万个话题吗?

因此,如果正在使用一个主题,您必须使用选择性消费者来使用来自该主题的消息,请参阅http://www.eaipatterns.com/MessageSelector.html 选择性消费者将做的是从主题中检索与某些匹配的消息标准。例如,将 JMS 消息发布到主题的消息生产者应该包括一个标题或一个名为 targetUser 的 JMS 属性或类似的东西,然后消费者可以说给出来自 AddressChangeTopic 的任何消息,其中自定义属性 targetUser="Joe"在此处查看一些示例选择器示例

关键是要意识到您可以像查询数据库表一样查询队列或主题,但查询语法非常有限。从概念的角度来看,我强烈推荐企业集成模式书http://www.amazon.ca/Enterprise-Integration-Patterns-Designing-Deploying/dp/0321200683

于 2013-01-08T05:08:35.550 回答
0

虚拟主题正是我一直在寻找的解决方案。它描述了问题和解决方案(用我所拥有的更简洁的话 :-) 请参阅“JMS 持久主题的限制”

于 2013-01-10T03:53:25.843 回答