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

时间:2009-10-17 07:07:24

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

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

  1. 创建客户发布到

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

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

  5. client->JMSDQ->DuplicatorMDB->Q1->MDB->System1
                               \->Q2->MDB->System2
    

    是否有类似的现有功能?如果一个或两个后端系统都关闭,那么平衡系统以保持系统稳定的正确方法是什么?

    应用程序服务器是WebLogic 10.

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

     
    client->Topic-->MDB1@server1->System1
               | \->MDB2@server1->System2 
               \---->MDB1@server2->System1 
                \--->MDB2@server2->System2 
    

    因此,每条消息将两次发送到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实施的错误或特征。

3 个答案:

答案 0 :(得分:1)

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

Configuration details

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

  

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

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