Apache camel 用';n';回复信息

Apache camel 用';n';回复信息,apache-camel,ibm-mq,camel-jms,Apache Camel,Ibm Mq,Camel Jms,我正在使用cameljms组件进行请求-应答,以便与MQ通信。对于我的一些请求,我可以收到回复信息。如何聚合这些回复消息 我曾想过使用聚合器模式和聚合策略,但不能使用它,因为我不确定可以回复的消息数量 社区能帮助我理解什么是正确的方法吗?我做了一些谷歌搜索,但找不到有用的东西。下面是我的示例路线代码 from("direct:"+routeName).routeId(routeName) .setHeader("JMS

我正在使用cameljms组件进行请求-应答,以便与MQ通信。对于我的一些请求,我可以收到回复信息。如何聚合这些回复消息

我曾想过使用聚合器模式和聚合策略,但不能使用它,因为我不确定可以回复的消息数量

社区能帮助我理解什么是正确的方法吗?我做了一些谷歌搜索,但找不到有用的东西。下面是我的示例路线代码

from("direct:"+routeName).routeId(routeName)
                        .setHeader("JMSCorrelationID", constant(UUID.randomUUID().toString()))
                        .circuitBreaker()
                            .resilience4jConfiguration()
                            .minimumNumberOfCalls(3)
                        .end()
                        .to(mqComponentBeanName+"://CAMELDEMO?exchangePattern=InOut&requestTimeout=10000&replyTo=CAMELDEMOREPLY")
                            .log("${body}")
                            .unmarshal(customerDetailsOutBound)
                            .process(new Processor() {
                                    @Override
                                    public void process(Exchange exchange) throws Exception {
                                        System.out.println(exchange.getIn().getBody().toString());
                                    }
                            })
                        .onFallback().process(new Processor() {
                            @Override
                            public void process(Exchange exchange) throws Exception {
                                System.out.println("Store this message to backup");
                            }
                        })
                        .end();

期待从社区中获得一些好的见解。谢谢。

好吧,传统的请求回复设计只有一条回复信息。等待响应的线程在第一个响应到达时立即停止侦听

使用JMS关联ID(每个请求没有专用线程),理论上可以为同一个请求接收多个响应,但我不知道这是否真的在JMS中有效/允许

根据评论进行更新

from(mqComponentBeanName+"://CAMELDEMOREPLY?
                          exchangePattern=In&requestTimeout=10000)
.aggregate(header("JMSCorrelationID"), new MyAggregationStrategy())
.to(mqComponentBeanName+"://CAMELDEMO_AGGREGATED_REPLY?
                          exchangePattern=Out&requestTimeout=10000)
您在评论中写道,您可以为一个请求接收多个JMS回复,甚至可以获得预期的答案数量

如果这一切都起作用,您可以在向调用者发送回复之前,使用驼峰路由中的来收集所有响应


聚合器是高度可配置的。您可以决定如何组合响应,还可以定义多个完成条件(超时、消息数量等)。

消息流

  • 您的第一条路由将消息发送到
    CAMELDEMO
    队列,并开始在新队列上等待单个聚合消息
    CAMELDEMO\u聚合的\u回复
  • CAMELDEMO
    上接收消息的组件,开始向cameldemopreply队列发送响应,并指示将发送多少响应
  • 下面的第二条路由开始侦听
    CAMELDEMOREPLY
    ,聚合消息并将聚合消息发送到
    CAMELDEMO\u aggregated\u REPLY
  • CAMELDEMO\u AGGREGATED\u reply
    上等待回复的第一条路由获取聚合回复,接收单个消息并将其发送回
  • 原始路线已更新,等待
    CAMELDEMO\u聚合\u回复

    ...
    .to(mqComponentBeanName+"://CAMELDEMO?exchangePattern=InOut&requestTimeout=10000&
                    replyTo=CAMELDEMO_AGGREGATED_REPLY")
    .log("${body}")
    .unmarshal(customerDetailsOutBound)
    .process(new Processor() {
            @Override
            public void process(Exchange exchange) throws Exception {
                System.out.println(exchange.getIn().getBody().toString());
            }
    })
    ....
    
    聚合消息的第二条路由

    from(mqComponentBeanName+"://CAMELDEMOREPLY?
                              exchangePattern=In&requestTimeout=10000)
    .aggregate(header("JMSCorrelationID"), new MyAggregationStrategy())
    .to(mqComponentBeanName+"://CAMELDEMO_AGGREGATED_REPLY?
                              exchangePattern=Out&requestTimeout=10000)
    

    我能用一条路线解决这个问题。解决方案可能并没有那么简单,但有效并实现了目的。我使用了loopDoWhile,在loopDoWhile内的处理器中,我使用普通java代码从队列中获取消息

    from("direct:"+routeName).routeId(routeName)
                        .setHeader("JMSCorrelationID", constant(UUID.randomUUID().toString()))
                        .circuitBreaker()
                            .resilience4jConfiguration()
                            .minimumNumberOfCalls(3)
                        .end()
                        .to(mqComponentBeanName+"://CAMELDEMO?exchangePattern=InOut&requestTimeout=10000&replyTo=CAMELDEMOREPLY")
                            .log("${body}")
                            .unmarshal(customerDetailsOutBound)
                            .process(new Processor() {
                                    @Override
                                    public void process(Exchange exchange) throws Exception {
                                        System.out.println(exchange.getIn().getBody().toString());
    
    
    int msgCount = getMsgCountfromFirstReposnse;
    if (msgCount > 1) {
    exchange.getIn().setHeader("COUNTER", 0);
    exchange.getIn().setHeader("MSG_COUNT", msgCount-1);
    exchange.setProperty("connectionFactory", connectionFactory);
    }
                                    }
                            })
                        .loopDoWhile(simple("${headers.COUNTER} != ${headers.MSG_COUNT}"))
                                .process(simpleJMSConsumerProcess)
                            .end().endCircuitBreaker()
                        .onFallback().process(new Processor() {
                            @Override
                            public void process(Exchange exchange) throws Exception {
                                System.out.println("Store this message to backup");
                            }
                        })
    
    处理器内部的代码:

    ConnectionFactory connectionFactory = (ConnectionFactory) exchange.getProperty("connectionFactory");
        Connection connection = connectionFactory.createConnection();
        Session session = connection.createSession(false,
                Session.AUTO_ACKNOWLEDGE);
    
        try {
            Queue queue = session.createQueue("CAMELDEMOREPLY?consumer.priority=10");
            MessageConsumer consumer = session.createConsumer(queue, "JMSCorrelationID = '"+exchange.getIn().getHeader("JMSCorrelationID").toString()+"'");
            connection.start();
            TextMessage textMsg = (TextMessage) consumer.receive();
            System.out.println(textMsg);
            System.out.println("Received: " + textMsg.getText());
            exchange.getIn().setHeader("COUNTER", ((Integer)exchange.getIn().getHeader("COUNTER"))+1);
            if (connection != null) {
                connection.close();
            }
        } finally {
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    

    Kavitha,不能这样做,因为请求-应答在单线程上工作。一旦收到回复,它就会向前移动。是的,客户端无法接收多个流式响应。客户端的HTTP请求。下游系统通过IBM MQ接收请求,并在应答队列中发送响应。对于某些请求,下游系统可以为相同的correlationID发送多个响应。所以,该路由的责任是在将响应返回给客户端的同时聚合所有这些请求。此外,来自MQ的应答/响应消息有一个字段,用于标识期望作为响应的消息数量。这也可以用于循环,但问题是如何使用这些剩余的消息,因为req repl在单线程上工作。在第3点中,如何获得必须聚合消息的JMSCorrelationId?这在第1点中可用。是,答复者需要设置“同意”。但第二条路线,不知道它必须聚合MSG的特定CorrelationId。现在明白你的意思了。您试图说根据correlationId聚合第二条路由中的每条消息。是的,这可能是一个相当大的解决方案。但是,它有创建新队列和读写操作的开销。与IBM MQ一样,它也有自己的成本。因此,该解决方案可以根据成本进行评估。但是,多回复解决方案的主要问题保持不变。您要等多久才能将请求视为已完成,并且不再需要回复?[我们对此有一个超时。因此这不是问题]回到单一回复解决方案:您必须在创建回复消息的位置聚合所有回复消息。[无法在发件人端进行此聚合。因为这不在我们的控制范围内。]我更新了我的答案,因为您在评论中提供了有关您案例的更多信息。@burik/@Kavitha我也了解聚合器EIP,我可以使用它。我看到的唯一问题是如何解决这个问题:使用JMS关联ID(每个请求没有专用线程),理论上可以为同一个请求接收多个响应,但我不知道这是否真的在JMS中有效/允许。request-reply在这里工作得很好。唯一关心的是如何使线程等待其他回复,或者如何基于相同的correlationId聚合其他回复