funcmike / rabbitmq-nio

A Swift implementation of AMQP 0.9.1 protocol: decoder + encoder and non-blocking client
Apache License 2.0
44 stars 8 forks source link

Heartbeats never sent, only responded to? #49

Open tweidema opened 1 month ago

tweidema commented 1 month ago

Thank you very much for making this repo available. It is higly appreciated and enabled us to use Swift for a new project where we needed AMQP 0.9.1.

I have a question, which might be a change-request if I understand things correctly.

You write in the README

Connection to AMQP broker is sustained by answering to heartbeat messages

But as I understand heartbeats (and my experiments validate that), both the client and the rabbitmq server must regularly send heartbeats which the other side must then respond to.

I have a client that only listens to new messages, never sends any. It was disconnected from the server every 3 minutes and in rabbitmq log I saw this pattern repeated (ip's, user and vhost redacted)

2024-10-13 03:06:03.606625+02:00 [info] <0.845455.0> connection <0.845455.0> (x.y.z.x:
42266 -> x2.y2.z2.x2:5672 - RabbitMQNIO): user 'xxx' authenticated and granted access 
to vhost 'yyy'
2024-10-13 03:09:03.609114+02:00 [error] <0.845455.0> closing AMQP connection <0.845455.0>
 (x.y.z.x:42266 -> x2.y2.z2.x2:5672 - RabbitMQNIO):
2024-10-13 03:09:03.609114+02:00 [error] <0.845455.0> missed heartbeats from client, timeout: 60s

even though several messages were received by my client in that period.

Reading on https://www.rabbitmq.com/docs/heartbeats that

Any traffic (e.g. protocol operations, published messages, acknowledgements) counts for a valid heartbeat. Clients may choose to send heartbeat frames regardless of whether there was any other traffic on the connection but some only do it when necessary.

I rewrote the client from autoAck'ing incoming messages to manually acking them. That change made it stay connected, as long as any messages arrive within 3 minutes at least. As I understand it this is because the server considers the manual ack as a substitude for a heartbeat message.

I don't know why it takes 3 minutes instead of 1 for the server to disconnect my client, but maybe the server has a grace-value of "ok to miss 2 heartbeats"?

If my understanding of matters is correct I would like to request that the library also sends hearbeat if nothing has been sent from the client for "negotiated heartbeat timeout"/2 seconds.