0

我要求客户端发送的单个 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 条在 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 实现的错误或特性。

4

3 回答 3

1

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

配置细节

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

于 2009-10-17T07:12:24.743 回答
0

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

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

于 2009-10-17T09:53:21.493 回答
0

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

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

于 2009-10-17T17:20:15.607 回答