【问题标题】:How to "copy" a JMS message to 2 destinations?如何将 JMS 消息“复制”到 2 个目的地?
【发布时间】:2010-12-07 14:04:45
【问题描述】:

我有一个要求,客户端发送的单个 JMS 消息必须可靠地(仅一次)传递到两个系统。这两个系统没有启用 HA,所以我提出的最佳建议是:

  1. 创建客户端发布到的单个队列

  2. 设置两个“中间”队列

  3. 使用自定义“DuplicatorMDB”从客户端队列中读取消息并将它们发布到同一事务中的两个队列。

客户端->JMSDQ->DuplicatorMDB->Q1->MDB->System1 \->Q2->MDB->System2

有没有这样的现有功能?如果一个或两个后端系统出现故障,平衡系统以保持系统稳定的正确方法是什么?

应用服务器是WebLogic 10。

我不能为此使用主题,因为在集群中主题会导致过多的消息重复。如果我们有 2 个实例,那么主题会是这样的:

客户端->主题-->MDB1@server1->System1 | \->MDB2@server1->System2 \---->MDB1@server2->System1 \--->MDB2@server2->System2

因此,每条消息将被传送两次到 System1 和两次到 System2,如果集群中有 8 台服务器,则每条消息将被传送 8 次。这是我真正想避免的......

最后我有时间测试它,这是我观察到的: 一个集群中的 2 个节点。 2 个 JMS 服务器:节点 1 上的 jms1,节点 2 上的 jms2。 分布式主题 dt。具有持久订阅和 jms-client-id=durableSubscriber 的 MDB。启动系统:0 条消息,mdb@node1 已启动,mdb@node2 尝试定期连接,但无法连接,因为“客户端 id,durableSubscriber,正在使用中”。正如预期的那样。

已发送 100 条消息: jms1@dt 消息当前 = 0,消息总数 = 100,消费者当前 = 1 我可以看到 node1 处理了 100 条消息。
jms2@dt 消息当前 = 100,消息总数 = 100,消费者当前 = 1 即“重复”消息在主题中未决。

另外发送了 100 条消息,100 条在节点 1 上处理,200 条在节点 2 上待处理。

重新启动 node1,mdb@node2 重新连接到 dt 并开始处理“未决”消息。在 node2 上处理了 200 条消息。

node1启动后,mdb@node1无法连接dt,而mdb@node2是连接的。

jms1@dt 消息当前 = 0,消息总数 = 0,消费者当前 = 0
jms2@dt 消息当前 = 0,消息总数 = 200,消费者当前 = 1

再发送 100 条消息,我看到所有 100 条消息都在 node2 上处理并在 node1 上丢弃。

jms1@dt 消息当前 = 0,消息总数 = 100,消费者当前 = 0
jms2@dt 消息当前 = 0,消息总数 = 300,消费者当前 = 1

现在我重新启动 node2,mdb@node1 重新连接到 dt。重新启动后,mdb@node2 重新连接到 dt,mdb@node1 与 dt 断开连接。

jms1@dt 消息当前 = 0,消息总数 = 100,消费者当前 = 1
jms2@dt 消息当前 = 0,消息总数 = 0,消费者当前 = 1

我发送了 100 条消息,都在 node2 上处理并存储在 node1 上的主题中:

jms1@dt 消息当前 = 100,消息总数 = 200,消费者当前 = 1
jms2@dt 消息当前 = 0,消息总数 = 0,消费者当前 = 1

然后我关闭了 node2,在 mdb@node1 重新连接到主题后,我看到 node1 上正在处理 100 条“待处理消息”。

所以结果是: 我发送了 400 条消息,MDB 处理了 700 条,其中 300 条是重复的。

看起来 MDB 重新连接工作正常,但如果托管“活动”MDB 的节点出现故障,则消息可能会重复。

这可能是 weblogic JMS 实现的错误或特性。

【问题讨论】:

  • 我错过了什么吗?为什么不使用主题?
  • 对持久订阅有何反馈?

标签: java jms weblogic weblogic-10.x integration-patterns


【解决方案1】:

[...] 因此,每条消息将被传递两次到 System1 和两次到 System2,如果集群中有 8 台服务器,则每条消息将被传递 8 次。这是我真正想避免的......

这适用于非持久订阅,但不适用于持久订阅。对于持久性,所有 MDB 共享相同的连接 ID 和订阅 ID(默认基于 MDB 名称),因此一次只有一个 MDB 能够附加和接收消息。第一个尝试连接的 MDB 将成功连接,其他 MDB 将检测到冲突并失败,但会继续重试。因此,使用持久主题订阅应该可以解决问题。

【讨论】:

  • 我猜你的意思是持久订阅,因为这是接收者的属性,而不是主题。如果 MDB 具有持久订阅(并且它必须指定 ClientID 来执行此操作),那么它只能部署在集群中的一个节点上。在 WLS 中部署到第二个节点失败,因为已经有一个具有相同客户端 ID 的客户端。
  • 来自 WLS10 文档:“订阅 ID 在其主题上必须是唯一的,因此具有持久主题订阅的 MDB 不能在集群中的多个服务器实例上运行。” download.oracle.com/docs/cd/E12839_01/web.1111/e13719/…
  • 是的,这就是我的意思,我不够清楚。关于文档,我不确定您要显示什么。为什么不粘贴整个段落:“订阅 ID 在其主题上必须是唯一的,因此具有持久主题订阅的 MDB 不能在集群中的多个服务器实例上运行。在 MDB 的第一个实例在服务器上启动后集群中的实例,一个额外的 EJB 实例可以成功部署到另一个集群服务器上,但是当 MDB 启动时,检测到冲突并且该 MDB 实例无法完全连接到 JMS。"
  • 正如我所说,第一个 MDB 将成功连接,其他 MDB 将失败,但它们会继续重试。因此,如果第一个 MDB 的服务器崩溃,另一个 MDB 将取代他的位置。换句话说,您具有高可用性,但没有消息重复。这不是你想要的吗?这应该很容易通过原型来确认。
  • 嗯.. 我想我根本无法部署第二个 MDB,但也许我必须重新运行测试,会这样做。
【解决方案2】:

我没有使用过Weblogic,但是大多数JMS 解决方案都有队列和主题的概念。您需要一个 JMS 主题。订阅者注册,主题确保消息一次传递给每个订阅者。

Configuration details.

更新:如果您在集群环境中遇到问题,我会确保一切配置正确(这里是JMS Topic Clustering 的指南)。 Weblogic 在集群时会如此悲惨地失败,这绝对听起来很奇怪。如果这不起作用,您可以查看第 3 方消息队列,例如 RabbitMQ,它支持 JMS,绝对不会出现此问题。

【讨论】:

  • 集群中的主题存在问题,会创建过多的消息副本 - 请参阅帖子更新...
  • John 是正确的,RabbitMQ 将允许两个单独的订阅,并且无论集群中的节点数量如何,每个订阅都只会传递一个消息副本。
【解决方案3】:

这是 ESB 实现应该实现的那种行为。就处理开销而言,没有太大区别,但在“管道”和应用程序代码之间分离关注点会很有用。

事实上,WebSphere JMS 实现支持安装解决此类需求的中介。我不知道 WebLogic 是否有类似的东西,或者它们相关的 ESB 产品是否适合您,但我建议您研究这些功能。您目前有一个简单的要求,并且您的代码肯定就足够了,但是很容易想象一些小的附加要求(我们可以在传输到该目的地之前将此字段从美元转换为英镑,我们可以不发送消息这个内容到那个目的地...),瞧!您会发现自己正在编写自己的 ESB。

【讨论】:

  • 不需要 ESB IMO,这就是主题的用途。
  • 我继承了最初的主张,即无法使主题在提问者的情况下起作用。我认为您已经表示实际上可以使用主题,在这种情况下,我同意这将是可取的。同样的一般原则是,如果可能的话,尽量避免自己安装管道。
猜你喜欢
  • 2016-02-10
  • 2017-02-09
  • 2014-09-29
  • 2013-07-10
  • 1970-01-01
  • 2011-04-13
  • 2016-07-06
  • 2019-12-14
  • 1970-01-01
相关资源
最近更新 更多