Java管道破裂错误,RabbitMQ管道破裂错误或消息丢失

Using the pika library's BlockingConnection to connect to RabbitMQ, I occasionally get an error when publishing messages:

Fatal Socket Error: error(32, 'Broken pipe')

This is from a very simple sub-process that takes some information out of an in-memory queue and sends a small JSON message into AMQP. The error only seems to come up when the system hasn't sent any messages for a few minutes.

Setup:

connection = pika.BlockingConnection(parameters)

channel = self.connection.channel()

channel.exchange_declare(

exchange='xyz',

exchange_type='fanout',

passive=False,

durable=True,

auto_delete=False

)

Enqueue code catches any connection errors and retries:

def _enqueue(self, message_id, data):

try:

published = self.channel.basic_publish(

self.amqp_exchange,

self.amqp_routing_key,

json.dumps(data),

pika.BasicProperties(

content_type="application/json",

delivery_mode=2,

message_id=message_id

)

)

# Confirm delivery or retry

if published:

self.retry_count = 0

else:

raise EnqueueException("Message publish not confirmed.")

except (EnqueueException, pika.exceptions.AMQPChannelError, pika.exceptions.AMQPConnectionError,

pika.exceptions.ChannelClosed, pika.exceptions.ConnectionClosed, pika.exceptions.UnexpectedFrameError,

pika.exceptions.UnroutableError, socket.timeout) as e:

self.retry_count += 1

if self.retry_count < 5:

logging.warning("Reconnecting and resending")

if self.connection.is_open:

self.connection.close()

self.connect()

self._enqueue(message_id, data)

else:

raise e

This sometimes works on the second attempt. It often hangs for a while or just throws away messages before eventually throwing an exception (possibly related bug report). Since it only happens when the system is quiet for a few minutes I'm guessing it's due to a connection timeout. But AMQP has a heartbeat system and pika reportedly uses it (related bug report).

Why do I get this error or lose messages, and why won't the connection stay open when not in use?

解决方案

From another bug report:

As BlockingConnection doesn't handle heartbeats in the background and the heartbeat_interval can't override the servers suggested heartbeat interval (that's a bug too), i suggest that heartbeats should be disabled by default (rely on TCP keep-alive instead).

If processing a task in a consume block takes longer time then the server suggested heartbeat interval, the connection will be closed by the server and the client won't be able to ack the message when it's done processing.

An unreleased update may help with the issue.

So I implemented a workaround. Every 30 seconds I publish a heartbeat message through the queue. This keeps the connection open and has the added benefit of confirming to clients that my application is up and running.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值