一、发布

在发布/订阅模式中的角色是彼此陌生的。 一个发布者只是向世界说这个已经发生了,一位订阅者告诉世界“我在乎这个”。 在这个模型中,没有人关心特定的事件是很好的。 消息可能有一个订阅者,可能有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-发布/订阅的更多相关文章

  1. easynetq发布订阅demo实现注意事项

    最近开始在项目中使用easynetq,大概了解了下api,在网上看了下示例,结果没有一个运行成功的,一个最简单的发布订阅都没有成功.我是直接运行起来别人的示例,不应该啊,后来一直分析一直分析,最后发现 ...

  2. 【EasyNetQ】- 发布/订阅模式

    EasyNetQ支持的最简单的消息传递模式是发布/ 订阅.这种模式是消除消费者信息提供者的绝佳方式.出版商简单地向全世界说,“这已经发生了”或“我现在有了这些信息”.它不关心是否有人正在倾听,他们可能 ...

  3. EasyNetQ使用(九)【非泛型的发布&订阅扩展方法,发生错误的情况 】

    自从EasyNetQ第一个版本开始,它就可以发布/订阅特定类型的消息. bus.Subscribe<MyMessage>("subscriptionId", x =&g ...

  4. 17-EasyNetQ:非泛型的发布&订阅扩展方法

    自从EasyNetQ第一个版本开始,它就可以发布/订阅特定类型的消息. bus.Subscribe<MyMessage>("subscriptionId", x =&g ...

  5. RedisRepository封装—Redis发布订阅以及StackExchange.Redis中的使用

    本文版权归博客园和作者本人吴双共同所有,转载请注明本Redis系列分享地址.http://www.cnblogs.com/tdws/tag/NoSql/ Redis Pub/Sub模式 基本介绍 Re ...

  6. 15天玩转redis —— 第九篇 发布/订阅模式

    本系列已经过半了,这一篇我们来看看redis好玩的发布订阅模式,其实在很多的MQ产品中都存在这样的一个模式,我们常听到的一个例子 就是邮件订阅的场景,什么意思呢,也就是说100个人订阅了你的博客,如果 ...

  7. 第五章 --- 关于Javascript 设计模式 之 发布-订阅模式

    先来个最简单的 发布订阅模式 document.body.addEventListener('click',function(){ alert(123); }); document.body.clic ...

  8. 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载

    一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...

  9. 分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载

    一.分布式消息总线 在很多MIS项目之中都有这样的需求,需要一个及时.高效的的通知机制,即比如当使用者A完成了任务X,就需要立即告知使用者B任务X已经完成,在通常的情况下,开发人中都是在使用者B所使用 ...

  10. NetMQ(三): 发布订阅模式 Publisher-Subscriber

    ZeroMQ系列 之NetMQ 一:zeromq简介 二:NetMQ 请求响应模式 Request-Reply 三:NetMQ 发布订阅模式 Publisher-Subscriber 四:NetMQ ...

随机推荐

  1. spring in action 学习笔记八:用@Primary 或者@Qualifier消除@Autowired引起的歧义现象

    首先解释一下@Primary和@Qualifier这两个注解的意思:@Primary的意思是在众多相同的bean中,优先使用用@Primary注解的bean.而@Qualifier这个注解则指定某个b ...

  2. python爬虫 Scrapy2-- 爬取豆瓣电影TOP250

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  3. 带你正确的使用List的retainAll方法求交集

    一. retainAll 方法 public boolean retainAll(Collection<?> c) { //调用自己的私有方法 return batchRemove(c, ...

  4. hdu 5079 Square

    http://acm.hdu.edu.cn/showproblem.php?pid=5079 题意: n*n网格,每个格子可以涂黑色或白色,有的格子必须涂黑色 问最大白色正方形边长分别为0,1,2,… ...

  5. bzoj千题计划239:bzoj4069: [Apio2015]巴厘岛的雕塑

    http://www.lydsy.com/JudgeOnline/problem.php?id=4069 a!=1: 从高位到低位一位一位的算 记录下哪些位必须为0 dp[i][j] 表示前i个数分为 ...

  6. '增量赋值(augmented assignment)', 多么痛的领悟!

    '增量赋值(augmented assignment)', 多么痛的领悟! 深刻理解x += a 与 x = x + a 的不同: 按理说上面的两条语句是等价的, 功能上完全一样的. 之所以说不同, ...

  7. 让浏览器重新下载css文件,解决不刷新缓存的问题

    网站页面源代码中的css文件和js文件后面带一个问号,后面跟着一连串数字或字符,问号起不到实际作用,仅能当作后缀,如果用问号加参数的方法,可以添加版本号等信息 它的作用有:1.作为版本号,让自己方便记 ...

  8. Redis常见操作命令

    1.库相关 select 索引 => 选择库 dbsize => 查询当前库中Key的数量 flushdb => 清空当前库 flushall => 清空所有库(建议不要用,除 ...

  9. TCP长连接和短连接的区别【转】

    转自:https://www.cnblogs.com/onlysun/p/4520553.html 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接, ...

  10. 001_fpm打包命令详解

    使用fpm来制作rpm包 2017/2/22 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ...