RabbitMQ异步支持

时间:2015-08-12 09:31:13

标签: c# asynchronous rabbitmq

RabbitMQ .NET客户端是否有任何异步支持?我希望能够异步连接和使用消息,但到目前为止还没有找到办法。

(对于消费消息,我可以使用EventingBasicConsumer,但这不是一个完整的解决方案。)

为了给出一些背景信息,这是我目前如何使用RabbitMQ的示例(代码来自我的博客):

var factory = new ConnectionFactory() { HostName = "localhost" };

using (var connection = factory.CreateConnection())
{
    using (var channel = connection.CreateModel())
    {
        channel.QueueDeclare("testqueue", true, false, false, null);

        var consumer = new EventingBasicConsumer(channel);
        consumer.Received += Consumer_Received;
        channel.BasicConsume("testqueue", true, consumer);

        Console.ReadLine();
    }
}

4 个答案:

答案 0 :(得分:13)

Rabbit支持使用AsyncEventingBasicConsumer类调度异步消息处理程序。它与EventingBasicConsumer的工作方式类似,但允许您注册一个返回Task的回调。调度回调,RabbitMQ客户端等待返回的Task

var factory = new ConnectionFactory
{
    HostName = "localhost",
    DispatchConsumersAsync = true
};

using(var connection = cf.CreateConnection())
{
    using(var channel = conn.CreateModel())
    {
        channel.QueueDeclare("testqueue", true, false, false, null);

        var consumer = new AsyncEventingBasicConsumer(model);

        consumer.Received += async (o, a) =>
        {
            Console.WriteLine("Message Get" + a.DeliveryTag);
            await Task.Yield();
        };
    }

    Console.ReadLine();
}

答案 1 :(得分:6)

此时RabbitMeQ .NET客户端内置了async / await支持。 RabbitMQ .NET Client repository

上有一张打开的门票

答案 2 :(得分:1)

总结当前的async / TPL支持:

  • 正如@ paul-turner所提到的,现在有一个AsyncEventingBasicConsumer,您可以为Task注册事件并返回HandleBasicDeliver
  • 还有一个AsyncDefaultBasicConsumer,您可以覆盖Task等虚拟方法并返回async。原始PR here(看起来它也是在5.0中引入的?)
  • 根据对上述PR和this issue的最终评论,看起来他们正在开发一个新的,从头开始的.NET客户端,它将更全面地支持private function request($postdata){ $url = $this->service_url_private; $curl = curl_init($url); $curl_post_data = $postdata; // check if token authentication is used if (array_key_exists('token', $postdata )){ $token = $postdata['token']; $authorization = 'Authorization: Bearer ' . $token; // prepare curl for Bearer Token Authorization curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization)); } else { // otherwise use BASIC authentication if (array_key_exists('email', $postdata )){ $username = $postdata['email']; } if (array_key_exists('password', $postdata )){ $password = $postdata['password']; } // prepare curl for Basic Authentication curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($curl, CURLOPT_USERPWD, "$username:$password"); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data); curl_setopt($curl, CURLINFO_HEADER_OUT, true); // Detail information for debugging curl_setopt($curl, CURLOPT_VERBOSE,true); $curl_response = curl_exec($curl); // Detail information for debugging $info = curl_getinfo($curl); // Detail information for debugging curl_close($curl); var_dump($info); return $curl_response; } 操作,但我不是&# 39;看到与此努力的任何具体联系。

答案 3 :(得分:0)

这里有AsyncEventingBasicConsumer,它所做的全部工作就是await在收到消息时异步“事件处理程序”。这是这里唯一使异步的东西。通常,您不会从中获得任何利润,因为您只有一个“处理程序”。邮件仍被一对一处理。它们被同步处理!另外,由于等待是在Consumer内部完成的,因此您将失去对异常处理的控制。

让我猜想,通过异步消息处理,您表示一定程度的并行性。

我最终使用的是来自TPL Dataflow的ActionBlockActionBlock运行与您配置的任务一样多的任务,管理等待和并行处理。由于它是在任务而不是线程上运行的,因此只要它们真正是异步的,就可以用更少的资源进行管理。

  1. 常规EventingBasicConsumer调用actionBlock.Post(something)
  2. 对于并行处理,您需要告诉RMQ在ack之前向您发送N条消息:model.BasicQos(0, N, true);
  3. ActionBlock具有带有MaxDegreeOfParallelism属性的选项,该属性也需要设置为N。
  4. ActionBlock运行async Task,它们接收Consumer之前发布的数据。不应抛出任务,因为ActionBlock会停止对异常的所有处理。
  5. 请小心传递CancellationToken,并正确等待ActionBlock完成所有正在运行的任务:actionBlock.Complete(); await actionBlock.Completion;