[英]RabbitMQ pika.exceptions.ConnectionClosed (-1, "error(104, 'Connection reset by peer')")
I have a task queue in RabbitMQ with multiple producers (12) and one consumer for heavy tasks in a webapp.我在 RabbitMQ 中有一个任务队列,其中有多个生产者 (12) 和一个消费者,用于 webapp 中的繁重任务。 When I run the consumer it starts dequeuing some of the messages before crashing with this error:
当我运行消费者时,它会在出现此错误之前开始将一些消息出列:
Traceback (most recent call last):
File "jobs.py", line 42, in <module> jobs[job](config)
File "/home/ec2-user/project/queue.py", line 100, in init_queue
channel.start_consuming()
File "/usr/lib/python2.7/site-packages/pika/adapters/blocking_connection.py", line 1822, in start_consuming
self.connection.process_data_events(time_limit=None)
File "/usr/lib/python2.7/site-packages/pika/adapters/blocking_connection.py", line 749, in process_data_events
self._flush_output(common_terminator)
File "/usr/lib/python2.7/site-packages/pika/adapters/blocking_connection.py", line 477, in _flush_output
result.reason_text)
pika.exceptions.ConnectionClosed: (-1, "error(104, 'Connection reset by peer')")
The producers code is:生产者代码是:
message = {'image_url': image_url, 'image_name': image_name, 'notes': notes}
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='tasks_queue')
channel.basic_publish(exchange='', routing_key=queue_name, body=json.dumps(message))
connection.close()
And the only consumer's code (the one is clashing):唯一的消费者代码(那个是冲突的):
def callback(self, ch, method, properties, body):
"""Callback when receive a message."""
message = json.loads(body)
try:
image = _get_image(message['image_url'])
except:
sys.stderr.write('Error getting image in note %s' % note['id'])
# Crop image with PIL. Not so expensive
box_path = _crop(image, message['image_name'], box)
# API call. Long time function
result = long_api_call(box_path)
if result is None:
sys.stderr.write('Error in note %s' % note['id'])
return
# update the db
db.update_record(result)
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='tasks_queue')
channel.basic_qos(prefetch_count=1)
channel.basic_consume(callback_obj.callback, queue='tasks_queue', no_ack=True)
channel.start_consuming()
As you can see, there are 3 expensive functions for message.如您所见,消息有 3 个昂贵的函数。 One crop task, one API call and one database update.
一项裁剪任务、一项 API 调用和一项数据库更新。 Without the API call, que consumer runs smoothly.
没有API调用,que消费者运行流畅。
Thanks in advance提前致谢
Your RabbitMQ log shows a message that I thought we might see: 您的RabbitMQ日志显示一条消息,我认为我们可能会看到:
missed heartbeats from client, timeout: 60s
What's happening is that your long_api_call
blocks Pika's I/O loop. 发生的是您的
long_api_call
阻塞了Pika的I / O循环。 Pika is a very lightweight library and does not start threads in the background for you so you must code in such a way as to not block Pika's I/O loop longer than the heartbeat interval. Pika是一个非常轻量级的库,不会为您在后台启动线程,因此您必须以不阻塞Pika的I / O循环的时间长于心跳间隔的方式进行编码。 RabbitMQ thinks your client has died or is unresponsive and forcibly closes the connection.
RabbitMQ认为您的客户端已死亡或无响应,因此强行关闭了连接。
Please see my answer here which links to this example code showing how to properly execute a long-running task in a separate thread. 请在这里查看我的答案,该答案链接到此示例代码 , 该示例代码显示如何在单独的线程中正确执行长时间运行的任务。 You can still use
no_ack=True
, you will just skip the ack_message
call. 您仍然可以使用
no_ack=True
,只是跳过ack_message
调用。
NOTE: the RabbitMQ team monitors the
rabbitmq-users
mailing list and only sometimes answers questions on StackOverflow. 注意: RabbitMQ团队监视
rabbitmq-users
邮件列表 ,仅在某些情况下回答关于StackOverflow的问题。
Starting with RabbitMQ 3.5.5, the broker's default heartbeat timeout decreased from 580 seconds to 60 seconds.
从 RabbitMQ 3.5.5 开始,broker 的默认心跳超时从 580 秒减少到 60 秒。
See pika: Ensuring well-behaved connection with heartbeat and blocked-connection timeouts .请参阅鼠兔:确保具有心跳和阻塞连接超时的良好连接。
The simplest fix is to increase the heartbeat timeout:最简单的解决方法是增加心跳超时:
rabbit_url = host + "?heartbeat=360"
conn = pika.BlockingConnection(pika.URLParameters(rabbit_url))
# or
params = pika.ConnectionParameters(host, heartbeat=360)
conn = pika.BlockingConnection(params)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.