简体   繁体   English

RabbitMQ pika.exceptions.ConnectionClosed (-1, "error(104, 'Connection reset by peer')")

[英]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.

相关问题 RabbitMQ pika.exceptions.ConnectionClosed - RabbitMQ pika.exceptions.ConnectionClosed 在python中使用Rabbitmq时出现“ pika.exceptions.ConnectionClosed”错误 - Getting “pika.exceptions.ConnectionClosed” error while using rabbitmq in python 在python中使用rabbitmq时出现“pika.exceptions.ConnectionClosed”错误 - Getting “pika.exceptions.ConnectionClosed” error while using rabbitmq in python 鼠兔连接丢失错误:pika.exceptions.StreamLostError: Stream 连接丢失:ConnectionResetError(104, 'Connection reset by peer') - Pika connection lost Error: pika.exceptions.StreamLostError: Stream connection lost: ConnectionResetError(104, 'Connection reset by peer') 意外的pika.exceptions.ConnectionClosed异常 - Unexpected pika.exceptions.ConnectionClosed exception RabbitMQ:Pika连接被对等错误重置 - RabbitMQ: Pika Connections reset by peer error 对等的104管道故障和连接重置 - Broken pipe error and connection reset by peer 104 Python错误104,由同行重置连接 - Python Error 104, connection reset by peer 高负载下的Rabbitmq:Socket.error [Errno 104]对等重置连接 - Rabbitmq on high load: Socket.error [Errno 104] Connection reset by peer 获取 aiohttp.client_exceptions.ClientOSError: [Errno 104] Connection reset by peer error discord bot - Getting aiohttp.client_exceptions.ClientOSError: [Errno 104] Connection reset by peer error discord bot
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM