我们已经使用Rabbit设置了一些工作流环境。
它解决了我们的需求,但我想知道这样做是否也是好的做法,就像我们为计划任务所做的那样。
调度意味着没有任务关键的100%调整时间。因此,如果一个作业应该在60秒后重试,那么它确实意味着超过60秒,这取决于队列的处理时间。
我创建了一个Q_WAIT并制作了一些标题来传输设置。
让我们这样做:
工作人员正在Q_ACTION订阅
如果操作错过(例如smtp服务器无法访问)
- > (重新)将消息发布到Q_WAIT并设置properties.headers ["预定"] =时间+ 60秒
另一个进程循环每隔15秒通过方法pop()通过Q_WAIT中的所有消息而不是通过订阅
q_WAIT.pop(:ack => true) do |delivery_info,properties,body|...
if (properties.headers["scheduled"] has reached its time)
-> (Re-)Publish the message back to Q_ACTION
ack(message)
在每个循环之后,连接关闭,因此NOT(Re-)Published保留在Q_WAIT中,因为它们未被确认。
有人可以证实这是一种有效的做法。
答案 0 :(得分:3)
当然,您可以使用原始问题中描述的循环过程。
此外,您可以将Time-To-Live Extension与Dead Letter Exchanges extension一起使用。
首先,指定x-dead-letter-exchange
Q_WAIT
队列参数等于当前交换,x-dead-letter-routing-key
等于Q_ACTION
绑定的路由密钥。
然后在发布期间设置x-message-ttl
队列参数集或设置消息expires属性,如果您需要自定义每消息ttl(尽管有一些well-known caveats这不是最佳实践,但它也有效)
在这种情况下,您的邮件将在他们的ttl到期后立即从Q_WAIT
传递到Q_ACTION
,而不会有任何额外的消费者,这更加可靠和稳定。
注意,如果您需要高级重新发布逻辑(更改邮件正文,属性),则需要使用其他队列(比如Q_PRE_ACTION
)来使用消息,更改它们然后发布到目标队列(比如{{1 }})。
答案 1 :(得分:0)
正如评论中所提到的,我尝试了x-dead-letter-exchange
的这个功能,它适用于大多数要求。一个问题/误解是TTL-PER-MESSAGE选项。
请看这里的例子。根据我的理解:
我希望第二条消息应该在发布3秒后和第一条消息之前宣布。
但它没有这样的效果,两者都在10秒后可用。
问:消息到期是否应该否决DLQ ttl?
#!/usr/bin/env ruby
# encoding: utf-8
require 'bunny'
B = Bunny.new ENV['CLOUDAMQP_URL']
B.start
DELAYED_QUEUE='work.later'
DESTINATION_QUEUE='work.now'
def publish
ch = B.create_channel
# declare a queue with the DELAYED_QUEUE name
q = ch.queue(DELAYED_QUEUE, :durable => true, arguments: {
# set the dead-letter exchange to the default queue
'x-dead-letter-exchange' => '',
# when the message expires, set change the routing key into the destination queue name
'x-dead-letter-routing-key' => DESTINATION_QUEUE,
# the time in milliseconds to keep the message in the queue
'x-message-ttl' => 10000,
})
# publish to the default exchange with the the delayed queue name as routing key,
# so that the message ends up in the newly declared delayed queue
ch.basic_publish('message content 1 ' + Time.now.strftime("%H-%M-%S"), "", DELAYED_QUEUE, :persistent => true)
puts "#{Time.now}: Published the message 1"
# wait moment before next publish
sleep 1.0
# puts this with a shorter ttl
ch.basic_publish('message content 2 ' + Time.now.strftime("%H-%M-%S"), "", DELAYED_QUEUE, :persistent => true, :expiration => "3000")
puts "#{Time.now}: Published the message 2"
ch.close
end
def subscribe
ch = B.create_channel
# declare the destination queue
q = ch.queue DESTINATION_QUEUE, durable: true
q.subscribe do |delivery, headers, body|
puts "#{Time.now}: Got the message: #{body}"
end
end
subscribe()
publish()
sleep