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