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();
}
}
答案 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
支持:
AsyncEventingBasicConsumer
,您可以为Task
注册事件并返回HandleBasicDeliver
。AsyncDefaultBasicConsumer
,您可以覆盖Task
等虚拟方法并返回async
。原始PR here(看起来它也是在5.0中引入的?)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的ActionBlock
。 ActionBlock
运行与您配置的任务一样多的任务,管理等待和并行处理。由于它是在任务而不是线程上运行的,因此只要它们真正是异步的,就可以用更少的资源进行管理。
EventingBasicConsumer
调用actionBlock.Post(something)
。ack
之前向您发送N条消息:model.BasicQos(0, N, true);
MaxDegreeOfParallelism
属性的选项,该属性也需要设置为N。async Task
,它们接收Consumer之前发布的数据。不应抛出任务,因为ActionBlock会停止对异常的所有处理。CancellationToken
,并正确等待ActionBlock完成所有正在运行的任务:actionBlock.Complete(); await actionBlock.Completion;