16、Publisher Confirms 发布者确认

AMQP发布消息默认情况下是非事务性的,也不能确保你的消息真正送达代理服务器(RabbitMQ)。尽管AMQP也可以指定事务性发布,但是在RabbitMQ上这个传输速度非常慢(所以RabbitMQ不推荐使用事务性发布,而是提出'Publish Confirms')。所以我们也没有让EasyNetQ API去支持事务性发布。为了高效且确保投递成功,RabbitMQ推荐使用'Publish Confirms'方式。简单来讲这是RabbitMQ对AMQP的一个扩展,当你的消息被RabbitMQ成功接收以后,提供了一个回调支持。

到底怎么才算成功接收,成功接收意味着什么呢?

  • 当一个瞬间消息进入消息队列时,说明RabbitMQ确定已收到该发布消息。
  • 当一个持久化消息被保存到磁盘,或者在每个队列上被消费时,说明RabbitMQ确定已收到该发布的持久消息。
  • 当一个瞬间消息被发现无法路由时,RabbitMQ直接确定已收到该发布消息。

更多关于消息确认方面的内容,请看the announcement on the RabbitMQ blog.

启用消息确认,需要通过在连接字符串中设置 publisherConfirms=true.

bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=true;timeout=10");

同步的发布方法bus.Publish(..)在返回之前会等待消息确认。在超时未收到确认(超时时间同样配置在连接字符串中)的,将产生异常抛出。在同步发布方法上启用发布者确认将明显变慢。如果有性能上的担心,你应该考虑使用异步发布方法PublishAsync()。

 1   bus.PublishAsync(new MyMessage
 2     {
 3         Text = "Hello World"
 4     }).ContinueWith(task =>
 5         {
 6             // 这里仅仅检测task是否完成
 7             // 如果task完成,即使task处于出错状态,IsCompleted属性也是true
 8             // 如果要检测是否正确完成应该用 if (task.IsCompleted && !task.IsFaulted)
 9             if (task.IsCompleted) 
10             {//如果任务完成
11                 //Console.Out.WriteLine("{0} Completed", count);
12             }
13 if (task.IsFaulted) 14 {//如果任务执行出错 15 Console.Out.WriteLine("\n\n"); 16 Console.Out.WriteLine(task.Exception); 17 Console.Out.WriteLine("\n\n"); 18 } 19 });

 

发布者调用异步发布方法bus.PublishAsync(),在收到确认消息之前,方法就已经返回,接着执行发布之后的程序。如果没有确认消息,或者收到一个NACK确认,这个task将会完成,并且task.State属性是错误状态。

英文地址:https://github.com/EasyNetQ/EasyNetQ/wiki/Publisher-Confirms

posted on 2017-12-05 17:18  困兽斗  阅读(3507)  评论(0编辑  收藏  举报

导航