47.14. JMS 上的 request-reply
Camel 支持 Request Reply over JMS。本质上,当您向 JMS 队列发送消息时,Exchange 的 MEP 应该为 InOut。
Camel 提供了很多选项,来通过 JMS 配置请求/回复,这会影响性能和集群环境。下表总结了选项。
| 选项 | 性能 | 集群 | 描述 |
|---|---|---|---|
|
| 速度快 | 是 |
临时队列用作回复队列,由 Camel 自动创建。要使用此选项,请不要 指定 replyTo 队列名称。另外,您还可以配置 |
|
| 速度较慢 | 是 |
共享持久队列用作回复队列。必须先创建队列,但某些代理可以实时创建它们,如 Apache ActiveMQ。要使用此功能,您必须指定 replyTo 队列名称。另外,您还可以配置 |
|
| 速度快 | 否(*是) |
专用持久队列用作回复队列。必须先创建队列,但某些代理可以实时创建它们,如 Apache ActiveMQ。要使用此功能,您必须指定 replyTo 队列名称。此外,您必须配置 |
|
| 速度快 | 是 |
允许使用并发消息监听程序同时处理回复消息。您可以使用 |
|
| 速度快 | 是 |
允许使用并发消息监听程序同时处理回复消息。您可以使用 |
JmsProducer 检测到 InOut,并提供 JMSReplyTo 标头,其中包含要使用的回复目的地。默认情况下,Camel 使用临时队列,但您可以使用端点上的 replyTo 选项指定固定回复队列(请参阅以下关于固定回复队列的信息)。
Camel 将自动设置侦听回复队列的消费者,因此 您不应 执行任何操作。
这个消费者是一个 Spring DefaultMessageListenerContainer,用于侦听回复。但是,它被修复为 1 个并发消费者。
这意味着,回复将按顺序处理,因为只有 1 个线程来处理回复。您可以使用 concurrentConsumers 和 maxConcurrentConsumers 选项将监听程序配置为使用并发线程。这可让您在 Camel 中更轻松地进行配置,如下所示:
from(xxx)
.inOut().to("activemq:queue:foo?concurrentConsumers=5")
.to(yyy)
.to(zzz);
from(xxx)
.inOut().to("activemq:queue:foo?concurrentConsumers=5")
.to(yyy)
.to(zzz);
在这个路由中,我们指示 Camel 使用有 5 个线程的线程池异步路由回复。
47.14.2. 通过 JMS 进行请求回复,并使用一个专用的固定回复队列 复制链接链接已复制到粘贴板!
在上例中,Camel 会预计名为"bar"的固定回复队列是共享的,因此它使用 JMSSelector 仅消耗它期望的回复消息。但是,由于 JMS 选择器会较慢,所以这样做有一个缺陷。此外,回复队列上的消费者使用新的 JMS 选择器 ID 进行更新较慢。实际上,它只在 receiveTimeout 选项超时时更新,默认为 1 秒。因此,在理论上,回复消息可能需要大约 1 秒才会被检测到。另一方面,如果固定的回复队列专用于 Camel 回复消费者,我们可以避免使用 JMS 选择器,因此更高性能。实际上,像使用临时队列一样快。有 ReplyToType 选项,您可以将它配置为 Exclusive
来告知 Camel 回复队列是独占的,如下例所示:
from(xxx)
.inOut().to("activemq:queue:foo?replyTo=bar&replyToType=Exclusive")
.to(yyy)
from(xxx)
.inOut().to("activemq:queue:foo?replyTo=bar&replyToType=Exclusive")
.to(yyy)
请记住,队列必须为每个端点和每个端点排斥。因此,如果您有两个路由,则每个路由都需要一个唯一的回复队列,如下例所示:
如果您在集群环境中运行,则同样适用。然后,集群中的每个节点都必须使用唯一的回复队列名称。如其他情况下,集群中的每个节点可能会获取旨在作为另一节点上的回复的消息。对于集群环境,建议改为使用共享回复队列。