[rabbitmq-discuss] RequestedHeartbeat

Geoffrey Anderson mrcoder at yahoo.com
Wed May 14 03:37:46 BST 2008


So I discovered more about how RabbitMQ works.  It gets interesting.

I find that if my application does this while preparing the ConnectionFactory:

mqFactory.Parameters.RequestedHeartbeat = 20;

Then I can post a new message to a queue without errors, as long as I call this line
of code, when I count out loud to myself to one or two:

mqModel.BasicPublish(mqTicket, mqExchange, mqRoutingKey, null,
builder.GetContentBody());                

But if I count to four out loud and then I call it, I get this exception:

AMQP close-reason, initiated by Library, code=541, text=\"Unexpected Exception\",
classId=0, methodId=0, cause=System.IO.IOException: Unable to read data from the
transport connection: A connection attempt failed because the connected party did
not properly respond after a period of time, or established connection failed
because connected host has failed to respond. --->
System.Net.Sockets.SocketException: A connection attempt failed because the
connected party did not properly respond after a period of time, or established
connection failed because connected host has failed to respond\r\n   at
System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size,
SocketFlags socketFlags)\r\n   at System.Net.Sockets.NetworkStream.Read(Byte[]
buffer, Int32 offset, Int32 size)\r\n   --- End of inner exception stack trace
---\r\n   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset,
Int32 size)\r\n   at System.IO.Stream.ReadByte()\r\n   at
System.IO.BinaryReader.ReadByte()\r\n   at
RabbitMQ.Client.Impl.Frame.ReadFrom(NetworkBinaryReader reader)\r\n   at
RabbitMQ.Client.Impl.SocketFrameHandler_0_9.ReadFrame()\r\n   at
RabbitMQ.Client.Impl.ConnectionBase.MainLoopIteration()\r\n   at
RabbitMQ.Client.Impl.ConnectionBase.MainLoop()



Furthermore, I find that if my application does this while preparing the
ConnectionFactory:

mqFactory.Parameters.RequestedHeartbeat = 50;  //Notice it's five-zero now...

Then I can post a new message to a queue without errors, as long as I call this line
of code, when I count out loud to myself to one or two or three or four:

mqModel.BasicPublish(mqTicket, mqExchange, mqRoutingKey, null,
builder.GetContentBody());                

But if I count to six out loud and then I call it, I get this exception:

AMQP close-reason, initiated by Library, code=541, text=\"Unexpected Exception\",
classId=0, methodId=0, cause=System.IO.IOException: Unable to read data from the
transport connection: A connection attempt failed because the connected party did
not properly respond after a period of time, or established connection failed
because connected host has failed to respond. --->
System.Net.Sockets.SocketException: A connection attempt failed because the
connected party did not properly respond after a period of time, or established
connection failed because connected host has failed to respond\r\n   at
System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size,
SocketFlags socketFlags)\r\n   at System.Net.Sockets.NetworkStream.Read(Byte[]
buffer, Int32 offset, Int32 size)\r\n   --- End of inner exception stack trace
---\r\n   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset,
Int32 size)\r\n   at System.IO.Stream.ReadByte()\r\n   at
System.IO.BinaryReader.ReadByte()\r\n   at
RabbitMQ.Client.Impl.Frame.ReadFrom(NetworkBinaryReader reader)\r\n   at
RabbitMQ.Client.Impl.SocketFrameHandler_0_9.ReadFrame()\r\n   at
RabbitMQ.Client.Impl.ConnectionBase.MainLoopIteration()\r\n   at
RabbitMQ.Client.Impl.ConnectionBase.MainLoop()


Isn't that an interesting coincidence?

Now I thought I would do a thought experiment.

Let's say I have an application in which I don't have the luxury to know in advance
exactly when the next queue message is going to arrive to be inserted to my queue. 
For example it might be on each new visitor to a web site.  Who knows when the next
visitor is going to visit my web site.  Let's assume its a pretty obscure web site,
and I'm not a very good marketer, which is not far from the truth.  (My
queue-insertion program is running in a specially prepared Windows service, and not
within the HTTP request context, so don't worry about HTTP being "sessionless" -- it
has nothing to do with my queue-insertion program.)

If I follow along the apparent trend, the way to prevent the exception in this
application is this line of code:

mqFactory.Parameters.RequestedHeartbeat = 5000000000000;


Is it going to work?  Just some food for thought. ;)

I looked at my connection's AutoClose property: It is false.

One conceivable solution would be to change the application design to use a
short-duration connection model, like the old days uwing Microsoft Transaction
Server's recommended practices.

Why did I write my app using a long-duration AMQP model in the first place?

2.2.4 The Connection Class
AMQP is a connected protocol. The connection is designed to be longlasting.

https://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.pdf?version=1


Now what should I do with my application?

(Be nice.)

I guess the pragmatic answer must be, never mind the design of AMQP for now:  If
short lived connections reliably don't throw exceptions, then I'm going to use short
lived connections in my long running Windows service (server) program.

It would be great to hear some hard won advice if possible from others to save time
from those who have maybe been down this road.  

I don't know which of these objects *in practice* are better long-lived, or better
short-lived:  Factory, Connection, Model, Ticket.

And what are the constraints:  Is a ticket supposed to span connections?  Is a
ticket supposed to span models (ie., mqConnection.CreateModel())?  etc, etc.  

Or is it best in practice to construct all of these objects every time I insert
another queue item?

I can of course study the authoritative document for design advice:

https://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.pdf?version=1

But if this beginning part is already not so accurate: "AMQP is a connected
protocol. The connection is designed to be longlasting"  then the rest of the advice
is likewise only half-accurate as well.  Time for lotta experimentation.  If I have
the time.  Some hard choices ahead, again.  I've been making hard choices every 3
days for like 2 weeks.  Grr.... I've never used IBM MQ Series.  But I'm beginning to
understand.


Thanks for reading.

Geoffrey




More information about the rabbitmq-discuss mailing list