Wait for a single RabbitMQ message with a timeout

后端 未结 5 1611
礼貌的吻别
礼貌的吻别 2020-12-15 12:53

I\'d like to send a message to a RabbitMQ server and then wait for a reply message (on a \"reply-to\" queue). Of course, I don\'t want to wait forever in case the applicatio

相关标签:
5条回答
  • 2020-12-15 13:18

    Here's what I ended up doing in the .NET client:

    protected byte[] WaitForMessageWithTimeout(string queueName, int timeoutMs)
    {
        var consumer = new QueueingBasicConsumer(Channel);
        var tag = Channel.BasicConsume(queueName, true, null, consumer);
        try
        {
            object result;
            if (!consumer.Queue.Dequeue(timeoutMs, out result))
                throw new ApplicationException(string.Format("Timeout ({0} seconds) expired while waiting for an MQ response.", timeoutMs / 1000.0));
    
            return ((BasicDeliverEventArgs)result).Body;
        }
        finally
        {
            Channel.BasicCancel(tag);
        }
    }
    

    Unfortunately, I cannot do the same with py-amqplib, because its basic_consume method does not call the callback unless you call channel.wait() and channel.wait() doesn't support timeouts! This silly limitation (which I keep running into) means that if you never receive another message your thread is frozen forever.

    0 讨论(0)
  • 2020-12-15 13:20

    I just added timeout support for amqplib in carrot.

    This is a subclass of amqplib.client0_8.Connection:

    http://github.com/ask/carrot/blob/master/carrot/backends/pyamqplib.py#L19-97

    wait_multi is a version of channel.wait able to receive on an arbitrary number of channels.

    I guess this could be merged upstream at some point.

    0 讨论(0)
  • 2020-12-15 13:25

    This seems to break the whole idea of asynchronous processing, but if you must I think the right way to do it is to use an RpcClient.

    0 讨论(0)
  • 2020-12-15 13:26

    Rabbit now allows for you to add timeout events. Simply wrap your code in a try catch and then throw exceptions in the TimeOut and Disconnect handlers:

    try{
        using (IModel channel = rabbitConnection.connection.CreateModel())
        {
            client = new SimpleRpcClient(channel, "", "", queue);
            client.TimeoutMilliseconds = 5000; // 5 sec. defaults to infinity
            client.TimedOut += RpcTimedOutHandler;
            client.Disconnected += RpcDisconnectedHandler;
            byte[] replyMessageBytes = client.Call(message);
            return replyMessageBytes;
        }
    }
    catch (Exception){
        //Handle timeout and disconnect here
    }
    private void RpcDisconnectedHandler(object sender, EventArgs e)
    {
         throw new Exception("RPC disconnect exception occured.");
    }
    
    private void RpcTimedOutHandler(object sender, EventArgs e)
    {
         throw new Exception("RPC timeout exception occured.");
    }
    
    0 讨论(0)
  • 2020-12-15 13:31

    There's an example here using qpid with a msg = q.get(timeout=1) that should do what you want. Sorry, I don't know what other AMQP client libraries implement timeouts (and in particular I don't know the two specific ones you mentioned).

    0 讨论(0)
提交回复
热议问题