问题
我有一个RabbitMQ 服务器,用作我的一个系统的队列集线器。在过去一周左右的时间里,它的生产者每隔几个小时就会完全停止。
我试过什么
蛮力
- 停止消费者会释放锁几分钟,然后阻塞返回。
- 重启 RabbitMQ 解决了几个小时的问题。
- 我有一些自动脚本可以执行丑陋的重启,但它显然远非正确的解决方案。
分配更多内存
按照cantSleepNow 的回答,我已将分配给 RabbitMQ 的内存增加到 90%。服务器拥有高达 16GB 的内存,并且消息数量不是很高(每天数百万),所以这似乎不是问题。
从命令行:
sudo rabbitmqctl set_vm_memory_high_watermark 0.9
并与/etc/rabbitmq/rabbitmq.config
:
[
{rabbit,
[
{loopback_users, []},
{vm_memory_high_watermark, 0.9}
]
}
].
代码与设计
我为所有消费者和生产者使用 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()
消费者
消费者之间略有不同,但通常使用以下模式 - 打开连接,并等待它直到消息到达。连接可以长时间保持打开状态(例如,几天)。
with Connection('amqp://whatever:whatever@whatever:whatever//') as conn:
while True:
queue = conn.SimpleQueue(queue_name)
message = queue.get(block=True)
message.ack()
设计推理
- 消费者始终需要与队列服务器保持开放连接
- 生产者会话应该只存在于 API 调用的生命周期内
直到大约一周前,这种设计还没有引起任何问题。
Web 视图仪表板
Web 控制台显示消费者进入127.0.0.1
并172.31.38.50
阻止消费者访问172.31.38.50
、172.31.39.120
和。172.31.41.38
172.31.41.38
系统指标
为了安全起见,我检查了服务器负载。正如预期的那样,平均负载和 CPU 利用率指标很低。
为什么兔子MQ每次都会出现这样的死锁?