我要求客户端发送的单个 JMS 消息必须可靠地(仅一次)传递到两个系统。这两个系统没有启用 HA,所以我想出的最佳建议是:
创建客户端发布到的单个队列
设置两个“中间”队列
使用自定义的“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 条在 node1 上处理,200 条在 node2 上待处理。
重新启动 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 实现的错误或特性。