使用Apache Camel请求回复和分散聚集

时间:2014-08-06 16:46:38

标签: apache-camel

我正在尝试构建一条将执行以下操作的路线:

  1. 使用来自jms:sender-in的讯息。我正在使用INOUT请求回复模式。 JMSReplyTo = sender-out
  2. 上述邮件将路由到多个收件人,例如jms:consumer1-injms:consumer2-injms:consumer3-in。所有人都在使用请求回复模式。每个消费者指定 JMSReplyTo(在这种情况下,JMSReplyTo按此顺序jms:consumer1-out, jms:consumer2-out, jms:consumer3-out
  3. 我需要将所有回复汇总在一起,然后将结果发送回jms:sender-out
  4. 我构建了一条类似于此的路线:

    from("jms:sender-in")
        .to("jms:consumer1-in?exchangePattern=InOut&replyTo=queue:consumer1-out&preserveMessageQos=true")
        .to("jms:consumer2-in?exchangePattern=InOut&replyTo=queue:consumer2-out&preserveMessageQos=true")
        .to("jms:consumer3-in?exchangePattern=InOut&replyTo=queue:consumer3-out&preserveMessageQos=true");
    

    然后我将回复发送回某个队列以收集和聚合:

    from("jms:consumer1-out?preserveMessageQos=true").to("jms:gather");
    from("jms:consumer1-out?preserveMessageQos=true").to("jms:gather");
    from("jms:consumer1-out?preserveMessageQos=true").to("jms:gather");
    from("jms:gather").aggregate(header("TransactionID"), new GatherResponses()).completionSize(3).to("jms:sender-out");
    

    为了模仿我的消费者的行为,我添加了以下路线:

    from("jms:consumer1-in").setBody(body());
    from("jms:consumer2-in").setBody(body());
    from("jms:consumer3-in").setBody(body());
    

    我有几个问题:

    1. 我在回复中收到超时错误。如果我评论聚集部分,那么没有问题。即使回复返回队列然后转发到另一个队列,为什么会有超时。
    2. 如何存储原始JMSReplyTo值,以便Camel能够将聚合结果发送回发件人的回复队列。
    3. 我有一种感觉,我正在努力解决一些基本概念。任何帮助表示赞赏。 感谢。

1 个答案:

答案 0 :(得分:9)

一个好问题!

您需要考虑两件事

  1. 请勿混淆exchange patterns,请求回复(InOut)与事件 消息(InOnly)。 (除非你有充分的理由)。
  2. 如果您执行scatter-gather,则需要提出请求 multicast,否则它们将是pipelined而不是scatter-gather 真的是{{3}}。
  3. 我做了两个与你的案例相似的例子 - 一个有Request Reply,另一个有(单向)事件消息。

    随意用jms替换activemq组件 - 这些例子中的内容相同。

    示例一,使用事件消息 - InOnly:

    from("activemq:amq.in")
        .multicast()
            .to("activemq:amq.q1")
            .to("activemq:amq.q2")
            .to("activemq:amq.q3");
    
    from("activemq:amq.q1").setBody(constant("q1")).to("activemq:amq.gather");
    from("activemq:amq.q2").setBody(constant("q2")).to("activemq:amq.gather");
    from("activemq:amq.q3").setBody(constant("q3")).to("activemq:amq.gather");
    
    from("activemq:amq.gather")
        .aggregate(new ConcatAggregationStrategy())
            .header("breadcrumbId")
            .completionSize(3)
            .to("activemq:amq.out");
    
    from("activemq:amq.out")
        .log("${body}"); // logs "q1q2q3"
    

    示例二,使用请求回复 - 请注意散布路由必须在响应时收集响应。结果与第一个示例相同,但路由较少且配置较少。

    from("activemq:amq.in2")
        .multicast(new ConcatAggregationStrategy())
            .inOut("activemq:amq.q4")
            .inOut("activemq:amq.q5")
            .inOut("activemq:amq.q6")
        .end()
        .log("Received replies: ${body}"); // logs "q4q5q6"
    
    from("activemq:amq.q4").setBody(constant("q4"));
    from("activemq:amq.q5").setBody(constant("q5"));
    from("activemq:amq.q6").setBody(constant("q6"));
    

    关于你的问题二 - 当然,可以传递JMSReplyTo标头并强制交换模式 - 但是你将创建难以调试的代码。保持交换模式简单明了 - 它可以防止错误。