直接答复(Direct Reply-to)
直接答复是一个允许 RPC(请求/回复)客户端设计相似的一个特性,在教程6的例子中就是用这个避免每个请求都申明一个回复队列。
Motivation
RPC(请求/回复)是一个非常流程模式来实现像 RabbitMQ 的消息 broker。教程6 例子中实现了各种客户端。其中一个典型的方式就是用 RPC 客户端发送请求,并且被路由到一个长久的服务端队列。RPC 服务器通过客户端在 reply-to 头部信息中命名队列,来消费从这个队列过来的请求并回复所有客户端。
客户端的队列来自那?客户端能给每个请求/回复对申明一个单使用队列。但是这不高效;即使是临时的无镜像队列,创建和删除的成本也可能很高(与发送消息的成本相比)。尤其是在集群中所有的节点都同意队列已经创建,甚至它不是镜像的。
另一个客户端也可以针对回复创建一个长连接队列。但管理起来很繁琐,尤其是如果客户本身并不是长连接的话。
直接答复特性允许 RPC 客户端从它们的 RPC 服务器接收直接响应,不需要经过答复队列。这里的 “直接” 仍然意味着通过相同的连接和一个 RabbitMQ 节点。这里不存在直接网络连接 RPC 客户端和 RPC 服务端。
如何使用 Direct Reply-to
要使用直接答复,客户端需要以下两个步骤:
- 在 no-ack 模式中,从伪队列
amq.rabbitmq.reply-to消费。这里不需要首先声明这个“队列”,尽管如果它想的话,客户端可以这样做。 - 在它们的请求消息中将
reply-to设置为amq.rabbitmq.reply-to
然后 RPC 服务器将看到一个带有生成名称的 reply-to 属性。它应该发布到默认交换机(“”),并应该将 routing key 设置为这个值(比如像平常发送到应答队列一样)。这个消息然后就会被直接送到客户端消费了。
如果 RPC 服务器要执行一个很昂贵的计算,那么就可能会在执行客户端是否离开的检查。为此,服务器首先会在一个一次性 channel 中申明应答的名称,来决定它(客户端)是否还存在。请注意,即使你使用了 passive=false 来申明一个队列,这里并没有这种方式创建它,声明将会成功(0 条消息就绪,1 个使用者)或失败。
注意事项和限制
- RPC 客户端必须在自动确认模式中消费。这是因为如果客户端失去连接或拒绝应答消息,这里没有返回应答消息队列。
- 使用此机制发送的应答消息通常不是容错的(fault-tolerant)。如果发布原始请求的客户端随后断开连接,它们将被丢弃。假设 RPC 客户端会重新连接并提交其它的请求。
- 在
basic.consume中使用amq.rabbitmq.reply-to以及像队列一样使用reply-to属性。但是它并不是,它不会被删除并且不会在管理插件以及rabbitmqctl list_queues出现。 - 如果 RPC 服务器设置了强制标签(mandatory flag),那么
amq.rabbitmq.reply-to.*就不会作队列处理了。如服务器仅只是以这个消息来发布消息,然后这个消息会被视为not routed。如果设置了强制标签,就会发送一个basic.return。
原文链接:https://www.rabbitmq.com/direct-reply-to.html