如何将JMS消息“复制”到2个目的地?

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

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

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

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

客户端 - > JMSDQ-> DuplicatorMDB-> Q1-> MDB->系统1
                            \  - > Q2-> MDB->系统2

有这样的现有function吗? 如果一个或两个后端系统都关闭,那么平衡系统以保持系统稳定的正确方法是什么?

应用程序服务器是WebLogic 10。

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

 
客户端 - >主题 - > MDB1 @ server1->系统1
            |  \  - > MDB2 @ server1->系统2 
            \ ----> MDB1 @ server2->系统1 
             \ ---> MDB2 @ server2->系统2 

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

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

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

在另外100条消息中发送,在node1上处理100个消息,在node2上处理200个消息。

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

在node1启动后,mdb @ node1无法连接到dt,而mdb @ node2已连接。

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

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

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

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

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

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

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

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

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

看起来MDB重新连接按预期工作良好,但如果托管“活动”MDB的节点发生故障,则消息可能会重复。

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

我没有使用过Weblogic,但是大多数JMS解决方案都有Queues和Topics的概念。 你想要一个JMS主题。 订户注册并且主题确保消息一次传递给每个订户。

配置细节 。

更新:如果您遇到群集环境中的问题,我会确保一切都配置正确(这里是JMS主题群集的指南)。 毫无疑问,当集群化时,Weblogic会如此悲惨地失败。 如果这不起作用,您可以查看支持JMS的第三方消息队列,例如RabbitMQ ,并且肯定不会出现此问题。

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

实际上,WebSphere JMS实现支持安装满足此类需求的中介。 我不知道WebLogic是否有类似的东西,或者他们的相关ESB产品是否适合你,但我建议调查这些function。 你目前有一个简单的要求,你的代码肯定是足够的,但是很容易想象一些小的额外要求(我们可以在传输到那个目的地之前将这个字段从美元转换成磅),我们是否可以发送消息这个内容到那个目的地……)和lo! 你发现自己编写了自己的ESB。

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

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

Interesting Posts