Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a RabbitMQ Client tell when it loses connection to the server?

Tags:

rabbitmq

If I'm connected to RabbitMQ and listening for events using an EventingBasicConsumer, how can I tell if I've been disconnected from the server?

I know there is a Shutdown event, but it doesn't fire if I unplug my network cable to simulate a failure.

I've also tried the ModelShutdown event, and CallbackException on the model but none seem to work.

EDIT----- The one I marked as the answer is correct, but it was only part of the solution for me. There is also HeartBeat functionality built into RabbitMQ. The server specifies it in the configuration file. It defaults to 10 minutes but of course you can change that.

The client can also request a different interval for the heartbeat by setting the RequestedHeartbeat value on the ConnectionFactory instance.

like image 779
Kelly Avatar asked Feb 22 '13 21:02

Kelly


People also ask

How do I check RabbitMQ connection?

Here are the recommended steps: Make sure the node is running using rabbitmq-diagnostics status. Verify config file is correctly placed and has correct syntax/structure. Inspect listeners using rabbitmq-diagnostics listeners or the listeners section in rabbitmq-diagnostics status.

What happens when RabbitMQ goes down?

If a queue is not durable, all messages will be lost if RabbitMQ is shut down for any reason. For messages to survive restarts, both of these configurations must be true. This article talks about RabbitMQ Durable queues extensively.

Where can I see RabbitMQ logs?

RabbitMQ Debian and RPM packages will set up logrotate to run weekly on files located in default /var/log/rabbitmq directory.

What is connection timeout in RabbitMQ?

The default connection timeout for the RabbitMQ connection factory is 600 seconds (at least in the Java client API), hence your 10 minutes. You can change this by specifying to the connection factory your timeout of choice.


2 Answers

This is an example of it, but the marked answer is what lead me to this.

var factory = new ConnectionFactory
{
    HostName = "MY_HOST_NAME",
    UserName = "USERNAME",
    Password = "PASSWORD",
    RequestedHeartbeat = 30
};

using (var connection = factory.CreateConnection())
{
    connection.ConnectionShutdown += (o, e) =>
    {                       
        //handle disconnect                            
    };

    using (var model = connection.CreateModel())
    {
        model.ExchangeDeclare(EXCHANGE_NAME, "topic");
        var queueName = model.QueueDeclare();

        model.QueueBind(queueName, EXCHANGE_NAME, "#"); 

        var consumer = new QueueingBasicConsumer(model);
        model.BasicConsume(queueName, true, consumer);

        while (!stop)
        {
            BasicDeliverEventArgs args;                       
            consumer.Queue.Dequeue(5000, out args);

            if (stop) return;

            if (args == null) continue;
            if (args.Body.Length == 0) continue;

            Task.Factory.StartNew(() =>
            {
                //Do work here on different thread then this one
            }, TaskCreationOptions.PreferFairness);
        }
    }
}

A few things to note about this.

I'm using # for the topic. This grabs everything. Usually you want to limit by a topic.

I'm setting a variable called "stop" to determine when the process should end. You'll notice the loop runs forever until that variable is true.

The Dequeue waits 5 seconds then leaves without getting data if there is no new message. This is to ensure we listen for that stop variable and actually quit at some point. Change the value to your liking.

When a message comes in I spawn the handling code on a new thread. The current thread is being reserved for just listening to the rabbitmq messages and if a handler takes too long to process I don't want it slowing down the other messages. You may or may not need this depending on your implementation. Be careful however writing the code to handle the messages. If it takes a minute to run and your getting messages at sub-second times you will run out of memory or at least into severe performance issues.

like image 136
Kelly Avatar answered Oct 14 '22 06:10

Kelly


I'm guessing that you're using the C# library? (but even so I think the others have a similar event).

You can do the following:

public class MyRabbitConsumer
{
  private IConnection connection;

  public void Connect()
  {
    connection = CreateAndOpenConnection();
    connection.ConnectionShutdown += connection_ConnectionShutdown;
  }

  public IConnection CreateAndOpenConnection() { ... }

  private void connection_ConnectionShutdown(IConnection connection, ShutdownEventArgs reason)
  {

  }
}
like image 28
kzhen Avatar answered Oct 14 '22 07:10

kzhen