我正在研究使用rabbitmq来管理我的应用程序的事件。更具体地说,我想:
一个典型的例子是我有200到800个队列,我想不允许并行超过8个工作人员。
我决定使用n + 1个队列和n + m个工作人员(n = 200到800和m = 8):
这是伪代码:
def queues_declare(channel):
channel.queue_declare(queue='type1', durable=True)
channel.queue_declare(queue='type1_callback', durable=True)
channel.queue_declare(queue='type2', durable=True)
def type1(channel):
def callback_type1(ch, method, properties, body):
channel.basic_publish(exchange='',
routing_key='type2',
body=body,
properties=pika.BasicProperties(
reply_to = "type1_callback",
correlation_id = method.delivery_tag,
delivery_mode = 2,
))
def callback_type1_callback(ch, method, properties, body):
ch.basic_ack(delivery_tag = properties.correlation_id)
ch.basic_ack(delivery_tag = method.delivery_tag)
queues_declare(channel)
channel.basic_qos(prefetch_count=1)
channel.basic_consume(callback_type1,
queue='type1')
channel.basic_consume(callback_type1_callback,
queue='type1_callback')
def type2(channel):
queues_declare(channel)
def callback_type2(ch, method, properties, body):
# XXX: do work !
channel.basic_publish(exchange='',
routing_key=properties.reply_to,
body='',
properties=pika.BasicProperties(
correlation_id = properties.correlation_id,
))
ch.basic_ack(delivery_tag = method.delivery_tag)
channel.basic_consume(callback_type2,
queue='type2')
所以,我的问题是:这是用rabbitmq实现我想要的正确方法吗?有没有更好的方法来控制并行性并确保FIFO处理?
答案 0 :(得分:0)
这里有几个问题。
保证FIFO顺序的唯一方法是使用单个队列来序列化访问。并且使用大量只是将消息重新发布到这个单一队列的工作人员实际上放松了一点保证 - 所以最好以消息将直接到达该队列的方式设置消息传递结构。 无论如何,最大的缺点是你的性能受到单核CPU性能的限制。
有一种方法可以仅使用RabbitMQ本身来限制并发性。您需要为此目的创建一个单独的队列,并使用等于所需并发级别的消息量预先填充它。然后你工作人员应该做的第一件事就是尝试得到那个信息,但不要承认它 - 所以这个消息将在这个非工作状态下悬挂一个工人的整个一生。当工作者死亡(或只是关闭AMQP连接)时,任何其他工作人员都可以访问该消息以获取它。但同样,那里有一个缺点 - 这只能在非集群环境中可靠地运行。例如。请参阅https://aphyr.com/posts/315-jepsen-rabbitmq,其中几乎正在测试这个用例。