我试图模拟以下场景
服务器发送' START'通过amqp
对工作进程执行的操作如下(假设先前提供channel
和action
,并且操作为START
并且有一些有效负载。)
channel.assertQueue('', { exclusive: true }).then(({ queue }) => {
const cId = uuid()
channel.consume(queue, (msg) => {
if (msg.properties.correlationId === cId) {
const response = JSON.parse(msg.content.toString())
console.log('response', response)
resolve(response)
}
}, { noAck: true })
const msg = JSON.stringify(action)
channel.sendToQueue(
QUEUE_NAME,
new Buffer(msg),
{ correlationId: cId, replyTo: queue }
)
}, reject)
工作人员获得START action
以及correlationId
和replyTo
队列名称,将有效负载添加到其自己的内部事务列表中,并响应{{1使用' START_SUCCESS'排队动作。
现在,工作人员将查看要执行的操作的内部列表并执行这些操作,并发出“更新”消息。通过相同的replyTo
队列将操作返回到服务器,因此服务器需要知道继续监听该队列以进行更新,并且需要知道哪个工作正在处理任何特定任务的更新。服务器足够智能,可以知道特定任务已经启动,因此在这种情况下不会再次发送它。
但是,当工作人员停止执行任务时,服务器需要知道哪个工作人员发送了“停止”操作。消息给。有没有办法让工作人员向服务器发回某种直接的amqp通道,服务器可以使用它来发送STOP消息?
答案 0 :(得分:1)
最简单的答案似乎是工人要创建一个"回复"队列,并在' START_SUCCESS'中将该标识符发送到服务器消息,以及在某个地方声明的服务器存储。
然而,我认为RabbitMQ的大部分功能来自于这样的事实:消息不是直接发布到队列,而是发布到交换机,它们的最终目的地是由它们的路由密钥决定的。 (按队列名称发布实际上是通过使用路由密钥作为队列名称的交换。)如果您不熟悉不同类型的交换,请通读the RabbitMQ Getting Started tutorials。
在这种情况下,您可以考虑发布和订阅彼此的更新,而不是考虑服务器和工作人员需要了解彼此的身份。如果所有内容都发布到交易所,那么服务器和工作人员实际上并不需要了解彼此的身份。
以下是我的工作方式:
jobs.new
发布START消息,其中路由密钥对作业类型和消息中的作业ID进行分类。jobs.status
,绑定密钥设置为作业ID。jobs.ready
)收到一条消息。jobs.ready.some_type
交换,并将作业ID作为绑定密钥。jobs.control
发布START_SUCCESS消息。jobs.status
交换机发送UPDATE消息;再次,路由密钥与作业ID匹配,因此服务器接收消息。jobs.status
交换发布STOP消息。从RabbitMQ方面来看,您有以下要素:
jobs.control
服务器发布新作业。如果所有工作人员都能处理所有工作,这可能是一个简单的扇出交换,或者它可能是一个主题交换,它将不同的工作队列路由到不同类型的工作人员。jobs.new
工作人员发布更新。这将是直接或主题交换,其路由键是或包含作业ID。jobs.status
服务器发布更新以控制现有作业。同样,这将是直接或主题交换,其路由键是或包含作业ID。jobs.control
队列或不同的jobs.ready
队列绑定到jobs.ready.some_type
交换。jobs.new
交换。或者,服务器进程可以为入站流量设置单个队列,只需从收到的消息中读取作业ID。jobs.status
交换。请注意,您可以将其他队列附加到这些交换中的任何一个以获取流量的副本,例如:用于记录或调试。对于主题交换,只需使用绑定密钥jobs.control
绑定额外队列,它将获得所有消息的副本,而不会中断任何现有绑定。