直接回复
概述
直接回复是一个允许 RPC(请求/回复)客户端(其设计类似于教程 6中演示的设计)避免为每个请求声明一个回复队列的功能。
动机
RPC(请求/回复)是一种使用消息代理(如 RabbitMQ)实现的流行模式。教程 6演示了它与各种客户端的实现。典型的方法是,RPC 客户端发送路由到长期存在的(已知)服务器队列的请求。RPC 服务器从该队列中消费请求,然后使用客户端在reply-to
标头中命名的队列向每个客户端发送回复。
客户端的队列来自哪里?客户端可以为每个请求-响应对声明一个单次使用的队列。但这效率低下;即使是短暂的非复制队列,创建和删除的成本也可能很高(与发送消息的成本相比)。这在集群中尤其如此,因为所有集群节点都需要同意队列已创建,同意其类型、复制参数和其他元数据。
因此,或者客户端可以为其回复创建一个长期存在的队列。但这可能难以管理,尤其是在客户端本身不是长期存在的情况下。
直接回复功能允许 RPC 客户端直接从其 RPC 服务器接收回复,而无需通过回复队列。“直接”在这里仍然意味着通过相同的连接和 RabbitMQ 节点;RPC 客户端和 RPC 服务器进程之间没有直接的网络连接。
如何使用直接回复
要使用直接回复,RPC 客户端应
以无确认模式从伪队列
amq.rabbitmq.reply-to
消费。无需首先声明此“队列”,尽管客户端可以这样做(如果需要)。将其请求消息中的
reply-to
属性设置为amq.rabbitmq.reply-to
。
然后,RPC 服务器将看到一个带有生成名称的reply-to
属性。它应该发布到默认交换机(""
),并将路由键设置为此值(即,就像通常发送到回复队列一样)。然后,消息将直接发送到客户端消费者。
如果 RPC 服务器要执行一些昂贵的计算,它可能希望检查客户端是否已断开连接。为此,服务器可以在可丢弃的通道上首先声明生成的回复名称,以确定它是否仍然存在。请注意,即使您使用passive=false
声明“队列”,也无法创建它;声明只会成功(有 0 条消息准备就绪和 1 个消费者)或失败。
注意事项和限制
RPC 客户端必须在自动确认模式下消费。这是因为如果没有队列来返回回复消息,则客户端断开连接或拒绝回复消息。
RPC 客户端必须对从
amq.rabbitmq.reply-to
消费和发布请求消息都使用相同的连接和通道。使用此机制发送的回复消息通常不是容错的;如果发布原始请求的客户端随后断开连接,它们将被丢弃。假设在这种情况下,RPC 客户端将重新连接并提交另一个请求。
名称
amq.rabbitmq.reply-to
在basic.consume
和reply-to
属性中被用作队列;但是它不是。它不能被删除,并且不会出现在管理插件或rabbitmqctl list_queues
中。如果 RPC 服务器在设置了强制标志的情况下发布,则
amq.rabbitmq.reply-to.*
将被视为不是队列;即,如果服务器仅发布到此名称,则消息将被视为“未路由”;如果设置了强制标志,则将发送basic.return
。