3,EasyNetQ-发布/订阅
一、发布
在发布/订阅模式中的角色是彼此陌生的。 一个发布者只是向世界说这个已经发生了,一位订阅者告诉世界“我在乎这个”。 在这个模型中,没有人关心特定的事件是很好的。 消息可能有一个订阅者,可能有200个,或者可能没有。 发布者不应该关心。 EasyNetQ实现这种模式。 如果您开始发布,并且没有订阅者已经开始,那么您的消息就会消失。 这是设计(先订阅,后发布,如果现发布,则消息会丢失)。
代码:
var message = new MyMessage { Text = "Hello Rabbit" };
bus.Publish(message);
二、订阅
EasyNetQ用户订阅消息类型(消息类的.NET类型)。 一旦通过调用Subscribe方法设置了类型的订阅,就会在RabbitMQ代理上创建一个持久性队列,并且任何类型的消息将被放置在队列中。 RabbitMQ将在连接时将队列中的任何消息发送给用户。
要订阅一个消息,我们需要给EasyNetQ一个消息到达时执行的操作。 我们通过订阅一个委托来做到这一点:
bus.Subscribe<MyMessage>("my_subscription_id", msg => Console.WriteLine(msg.Text));
现在每次发布MyMessage的一个实例,EasyNetQ将会调用我们的代理,并将消息的Text属性打印到控制台。
您传递给订阅的订阅ID很重要。 EasyNetQ将针对消息类型和订阅ID的每个独特组合在RabbitMQ代理上创建一个唯一的队列(消息类型+订阅ID=唯一的队列)。
每个对Subscribe的调用都会创建一个新的队列消费者。 如果您使用相同的消息类型和订阅ID来呼叫两次订阅,则将创建两个消费者从同一个队列中消费的消费者。 然后,RabbitMQ将轮流向每个消费者循环连续的消息。 这对扩展和工作分享非常有用。 假设您已经创建了处理特定消息的服务,但是工作正在重载。 只需启动该服务的新实例(在同一台机器上或另一台机器上),而无需配置任何内容,就可以自动缩放。
如果您使用不同的订阅ids但是相同的消息类型来呼叫两次订阅,那么您将创建两个队列,每个队列都有自己的消费者。 给定类型的每个消息的副本将被路由到每个队列,因此每个消费者将获得所有消息(该类型的消息)。 如果您有几个不同的服务,那些都关心相同的信息类型,这是非常好的。
写订阅回调委托时的注意事项
当从通过EasyNetQ订阅的队列接收到消息时,它们被放置在内存队列中。 一个线程坐在循环中,从队列中获取消息并调用其Action代理。 由于代理在一个线程上一次处理一次,所以您应该避免长时间运行的同步IO操作。 尽快从委托返回控制。
使用异步订阅
异步订阅允许您的用户委托立即返回任务,然后异步执行长时间运行的IO操作。 一旦长时间运行的订阅完成,只需完成任务。 在下面的示例中,我们使用异步IO操作(DownloadStringTask)向Web服务发出请求。 当任务完成时,我们在控制台上写一行。
bus.SubscribeAsync<MyMessage>("subscribe_async_test", message =>
new WebClient().DownloadStringTask(new Uri("http://localhost:1338/?timeout=500"))
.ContinueWith(task =>
Console.WriteLine("Received: '{0}', Downloaded: '{1}'",
message.Text,
task.Result)));
另一个例子会导致异常被抛出,如果有故障,那么会导致消息被放置在默认的错误队列上:
_bus.SubscribeAsync<MessageType>("Queue_Identifier",
message => Task.Factory.StartNew(() =>
{
//在这里执行一些操作
//如果有异常,则会导致任务完成,但任务发生错误
//在下面的继续处理
}).ContinueWith(task =>
{
if (task.IsCompleted && !task.IsFaulted)
{
// 一切都奏效了
}
else
{
// 不要抓住这一点,它被进一步上升到层次结构,并导致发送到默认错误队列
throw new EasyNetQException("Message processing exception - look in the default error queue (broker)");
}
}));
取消订阅
所有的订阅方法返回一个ISubscriptionResult。 它包含描述底层IConsumer使用的IExchange和IQueue的属性,如果需要,可以使用高级API IAdvancedBus进一步操作这些属性。
您可以随时通过在ISubscriptionResult实例或其ConsumerCancellation属性上调用Dispose来取消订户:
var subscriptionResult = bus.Subscribe<MyMessage>("sub_id", MyHandler);
...
subscriptionResult.Dispose();
// 这相当于 subscriptionResult.ConsumerCancellation.Dispose();
这将阻止EasyNetQ从队列中消费,并关闭消费者的频道。
请注意,处理IBus或IAdvancedBus实例也将取消所有消费者并关闭与RabbitMQ的连接。
不要在消息处理程序中调用subscriptionResult.Dispose()。 这将在EasyNetQ ACK消费者频道上的消息与subscriptionResult.Dispose()调用关闭该通道之间创建竞争条件。 由于EasyNetQ的内部架构,这些调用将在不同的线程上被调用,并且时序不是确定性的。
3,EasyNetQ-发布/订阅的更多相关文章
- easynetq发布订阅demo实现注意事项
最近开始在项目中使用easynetq,大概了解了下api,在网上看了下示例,结果没有一个运行成功的,一个最简单的发布订阅都没有成功.我是直接运行起来别人的示例,不应该啊,后来一直分析一直分析,最后发现 ...
- 【EasyNetQ】- 发布/订阅模式
EasyNetQ支持的最简单的消息传递模式是发布/ 订阅.这种模式是消除消费者信息提供者的绝佳方式.出版商简单地向全世界说,“这已经发生了”或“我现在有了这些信息”.它不关心是否有人正在倾听,他们可能 ...
- EasyNetQ使用(九)【非泛型的发布&订阅扩展方法,发生错误的情况 】
自从EasyNetQ第一个版本开始,它就可以发布/订阅特定类型的消息. bus.Subscribe<MyMessage>("subscriptionId", x =&g ...
- 17-EasyNetQ:非泛型的发布&订阅扩展方法
自从EasyNetQ第一个版本开始,它就可以发布/订阅特定类型的消息. bus.Subscribe<MyMessage>("subscriptionId", x =&g ...
- RedisRepository封装—Redis发布订阅以及StackExchange.Redis中的使用
本文版权归博客园和作者本人吴双共同所有,转载请注明本Redis系列分享地址.http://www.cnblogs.com/tdws/tag/NoSql/ Redis Pub/Sub模式 基本介绍 Re ...
- 15天玩转redis —— 第九篇 发布/订阅模式
本系列已经过半了,这一篇我们来看看redis好玩的发布订阅模式,其实在很多的MQ产品中都存在这样的一个模式,我们常听到的一个例子 就是邮件订阅的场景,什么意思呢,也就是说100个人订阅了你的博客,如果 ...
- 第五章 --- 关于Javascript 设计模式 之 发布-订阅模式
先来个最简单的 发布订阅模式 document.body.addEventListener('click',function(){ alert(123); }); document.body.clic ...
- 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载
一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...
- 分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载
一.分布式消息总线 在很多MIS项目之中都有这样的需求,需要一个及时.高效的的通知机制,即比如当使用者A完成了任务X,就需要立即告知使用者B任务X已经完成,在通常的情况下,开发人中都是在使用者B所使用 ...
- NetMQ(三): 发布订阅模式 Publisher-Subscriber
ZeroMQ系列 之NetMQ 一:zeromq简介 二:NetMQ 请求响应模式 Request-Reply 三:NetMQ 发布订阅模式 Publisher-Subscriber 四:NetMQ ...
随机推荐
- Tensorflow图像处理
Tensorflow图像处理主要包括:调整尺寸,图像翻转,调整色彩,处理标注框. 代码如下: #coding=utf-8 import matplotlib.pyplot as plt import ...
- How To Crawl A Web Page with Scrapy and Python 3
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...
- Hadoop生态圈-Azkaban实现hive脚本执行
Hadoop生态圈-Azkaban实现hive脚本执行 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客中在HDFS分布式系统取的数据,而这个数据的是有之前我通过MapRed ...
- gcc初步窥探
由于没有上过Linux编程这门课,所以Linux学得很水啊!!用来用去都是ls -al ; cd .. ;这些渣命令,尤其gcc都不知道什么东西来的,所以先学一下吧. 一.程序的编译过程 对于GUN编 ...
- linq中let关键字学习
linq中let关键字就是对子查询的一个别名,let子句用于在查询中添加一个新的局部变量,使其在后面的查询中可见. linq中let关键字实例 1.传统下的子查询与LET关键字的区别 C# 代 ...
- 20155224 2016-2017-2 《Java程序设计》第6周学习总结
20155224 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 Thread线程: 定义某线程后,要有 xxx.stard(); Thread.sleep( ...
- 第5月第27天 cocos2d
1. 流程是这样的: 在CCApplication的run函数中,显示设备链调用相应的场景显示函数drawScene来绘制场景,然后调用了CCScheduler的update函数,在这个函数里,对所有 ...
- 【技术知识】恶意PDF文件分析-PDFdump的问题
1.提醒 百度分析恶意PDF文件,很多都是推荐PDFdump.在某次沙箱产品分析出疑似高级威胁的PDF样本后,我使用PDFdump查看ShellCode的加密数据,分析后并没有找到相关的ShellCo ...
- arm交叉编译器gnueabi、none-eabi、arm-eabi、gnueabihf等的区别【转】
转自:https://www.cnblogs.com/deng-tao/p/6432578.html 博客来之于: http://www.veryarm.com/296.html 交叉编译工具链的命 ...
- RTS与CTS的含义【转】
转自:http://www.cnblogs.com/sunyubo/archive/2010/04/21/2282176.html 一.RS232标准中的RTS与CTS RTS,CTS------请求 ...