我已经看过这个问题的一些细节,但没有任何直接答案。
这是假设的环境:
- 20 个以 Java 为中心的服务器(即 Tomcat/Glassfish/Jboss/等等) 通过 HTTP 与客户端对话
- 服务器前面的 HTTP 负载均衡器不保证 每个客户端连接都会带您返回同一服务器。
- 其他任何事情都可以通过技术来实现。 (JMS/ Camel / Memcached/Hazelcast/任何)
我们希望 Joe 和他的浏览器(可能使用 Flash 或 HTML5 或任何客户端技术)接收发布到可供所有 20 个服务器使用的 JMS 主题的所有消息。
这是一个例子:
- Joe 的第一个 HTTP 连接到达服务器 A
- 服务器 A 现在有一个用于 Joe 的 HTTP session (通过 cookie 等)
- 服务器 A 为其订阅主题(基于他的 session ID 等)
- Joe 的 HTTP 连接结束。
- 已向该主题发布一条消息。
- Joe 再次建立连接,但这次由服务器 F 处理。
这对我来说是有点模糊的地方。
- 我们知道 Joe 返回时的 session ID(也许该 session 在所有服务器之间共享),但是 JMS 订阅又如何呢?如果服务器 F 必须再次向 Joe 订阅该主题,他是否刚刚错过了一条消息? A 是 Joe 可以从中检索该消息的唯一服务器,还是当他在 F 上订阅时可能会发生某种魔法,并且它只知道他没有收到消息(大概在 A 上等待他)。<
我想我有点不清楚“订阅”的作用(流程方面)以及它与集群服务器的关系。我正在使用长轮询(cometd)和 websockets 来帮助客户端在接收主题消息时做出响应,但必须考虑当有许多服务器可以处理连接和订阅时这将如何工作。我想避免服务器固定。
感谢您的指点。
编辑1:希望有一些澄清。我在这里指的是 BlazeDS 框架中提供的一些特定内容。它允许 HTTP 客户端订阅 JMS 主题并使用长轮询来实现近乎实时的客户端更新,但它要求一旦客户端命中服务器,所有请求都必须返回到该服务器。因此,它必须(以某种方式?)保持该服务器上该客户端的主题订阅处于 Activity 状态。我想摆脱这个要求(使用任何技术/框架)。
最佳答案
JMS 服务器会跟踪每个订阅,并区分持久订阅和非持久订阅。假设您有客户 A、B、C 和主题 T。
- 客户端 A 订阅主题 T 并等待消息
- 客户端B订阅主题T等待消息
- 客户端 C 对主题 T 进行持久订阅并等待消息
- 客户端 B 和 C 在消息 M 放入主题 T 之前几秒崩溃
- 客户端 A 获取消息 M 的副本,因为它已订阅并且当前连接到 jms 服务器
- 客户端 B 重新启动,但没有获取消息的副本,因为当消息到达主题时它尚未连接到 jms 服务器
- 客户端 C 重新启动并获取消息 M,因为它进行了持久订阅,JMS 服务器在 C 崩溃时保留了消息 M 的副本并等待 C 回来并声明该消息。
消息服务器上有一些管理设置,用于控制 jms 服务器在将消息发送到死信队列之前等待持久订阅者返回并声明消息的时间长度,或者控制 jms 上的最大消息数。正在等待订阅者回来并声明的主题。您确实需要在永不丢失消息与流消息和内存或磁盘空间不足之间进行平衡。
请注意,持久队列的概念与持久订阅者的概念不同。持久队列和主题通过在确认收到消息之前将队列和消息的内容写入磁盘来防止 JMS 服务器崩溃。持久订阅者是指当消息到达而客户端未连接时消息会发生什么情况。
旧答案。
将 JMS 服务器视为 SQL 数据库。从Web容器的角度来看,应该有一个到JMS服务器的连接池,所以你要做的就是获取到JMS服务器的连接并订阅一个主题。例如。
- JMS 服务器有一个名为 AddressChangeTopic 的主题
- 每个 tomcat 实例都有一个对 AddressChangeTopic 的订阅
- Joe/Jim/John 等的地址更改事件都转到同一个 AddressChangeTopic,而不是转到 JohnAddressTopic、JimAddressTopic 等,为应用程序的每个用户创建单独的主题是不切实际的,如果你有100万用户,你会有100万个话题吗?
因此,如果正在使用一个主题,您必须使用选择性使用者来使用来自该主题的消息,请参阅 http://www.eaipatterns.com/MessageSelector.html选择性消费者要做的就是从符合特定条件的主题中检索消息。例如,将 JMS 消息发布到主题的消息生产者应该包含一个 header 或一个名为 targetUser 的 JMS 属性或类似的内容,然后使用者可以说提供来自 AddressChangeTopic 的任何消息,其中自定义属性 targetUser="Joe"请参阅一些选择器示例 Here
关键是要认识到您可以像查询数据库表一样查询队列或主题,但查询语法非常有限。从概念角度来看,我强烈推荐《企业集成模式》一书 http://www.amazon.ca/Enterprise-Integration-Patterns-Designing-Deploying/dp/0321200683
关于java - 集群环境中 JMS 主题的 HTTP 使用者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14207943/