Python:Kombu + RabbitMQ死锁 - 队列被阻止或阻塞

Ada*_*tan 6 python deadlock rabbitmq blockingqueue kombu

问题

我有一个RabbitMQ服务器,作为我的一个系统的队列中心.在过去一周左右,它的制作人每隔几个小时就会完全停止.

我试过了什么

蛮力

  • 停止消费者会释放锁定几分钟,但随后阻止返回.
  • 重启RabbitMQ解决了几个小时的问题.
  • 我有一些自动脚本可以完成丑陋的重启,但显然远非正确的解决方案.

分配更多内存

cantSleepNow的回答之后,我将分配给RabbitMQ内存增加到90%.服务器有16GB的内存,消息数量不是很高(每天数百万),所以这似乎不是问题.

从命令行:

sudo rabbitmqctl set_vm_memory_high_watermark 0.9
Run Code Online (Sandbox Code Playgroud)

并与/etc/rabbitmq/rabbitmq.config:

[
   {rabbit,
   [
     {loopback_users, []},
     {vm_memory_high_watermark, 0.9}
   ]
   }
].
Run Code Online (Sandbox Code Playgroud)

代码与设计

我为所有消费者和生产者使用Python.

生产者

生产者是提供呼叫的API服务器.每当呼叫到达时,都会打开一个连接,发送一条消息并关闭连接.

from kombu import Connection

def send_message_to_queue(host, port, queue_name, message):
    """Sends a single message to the queue."""
    with Connection('amqp://guest:guest@%s:%s//' % (host, port)) as conn:
        simple_queue = conn.SimpleQueue(name=queue_name, no_ack=True)
        simple_queue.put(message)
        simple_queue.close()
Run Code Online (Sandbox Code Playgroud)

消费者

消费者彼此略有不同,但通常使用以下模式 - 打开连接,并等待消息到达.连接可以长时间保持打开状态(比如几天).

with Connection('amqp://whatever:whatever@whatever:whatever//') as conn:
    while True:
        queue = conn.SimpleQueue(queue_name)
        message = queue.get(block=True)
        message.ack()
Run Code Online (Sandbox Code Playgroud)

设计推理

  • 消费者总是需要与队列服务器保持开放连接
  • Producer会话应仅在API调用的生命周期内存在

直到大约一周前,这种设计没有引起任何问题.

Web视图仪表板

Web控制台显示,消费者127.0.0.1172.31.38.50阻止消费者172.31.38.50,172.31.39.120,172.31.41.38172.31.41.38.

阻止/阻止队列

系统指标

为了安全起见,我检查了服务器负载.正如预期的那样,负载平均值和CPU利用率指标很低.

在此输入图像描述

为什么兔子MQ每次都这么僵局?

ean*_*son 4

这很可能是由 RabbitMQ 3.6.2 管理模块中的内存泄漏引起的。此问题现已在 RabbitMQ 3.6.3 中修复,可在此处获取。

该问题本身已在此处进行描述,但也在 RabbitMQ 消息板上进行了广泛讨论;例如这里这里。众所周知,这会导致许多奇怪的问题,这里报告的问题就是一个很好的例子。

作为新版本发布之前的临时修复,您可以升级到新的 est 版本、降级到 3.6.1 或完全禁用管理模块。