EasyNetQ使用(三)【Publish与Subcribe】
EasyNetQ
支持的最简单的消息模式是发布/订阅.这个模式是一个极好的方法用来解耦消息提供者和消费者。消息发布者只要简单的对世界说,“这里有些事发生” 或者 “我现在有一个信息”。它不关心有没有人监听,或者接收者是谁,或者接收者在那里。我们能够添加和移除特定类型的消息的订阅者,不需发布者做任何的重新配置。我们也能够有多个发布者发布相同的消息,添加和删除发布者也不用其他的发布者或者订阅者做任何重新配置。
用EasyNetQ
发布消息(假定你已经重建了一个IBus
实例)
- 创建你自己的消息实例,可以是任何可序列化的
.NET
类型。 - 调用
IBus
上的Publish
方法,并传入你的消息实例。
代码如下:
var message = new MyMessage{ Text = "Hello Rabbit" };
bus.Publish(message);
为确保消息投递成功,请看Publisher Confirms
.
发布者和订阅者之间彼此是不知道对方的。发布者简单的对世界说“这儿有事情发生”,订阅者告诉世界“我关心这种事儿的发生”。在这个模型中这是很好的,没有人关心特定的事件。可能有一个订阅者关心这个消息,也可能有200个,或者没有人关心它。发布者不应该关心EasyNetQ
对这个消息模式的实现。假如你开始去发布消息,而没有任何订阅者曾经定义此消息,那么这个消息就简单的消失了。这是我们的设计意图。
一个EasyNetQ
订阅者订阅一种消息类型(消息类为.NET
类型)。通过调用Subcribe
方法一旦对一个类型设置了订阅,一个持久化队列就会在RabbitMQ broker
上被创建,这个类型的任何消息都会被发送到这个队列上。订阅者无论什么时候连接上,RabbitMQ
都将会将消息从队列中发送给订阅者。
不管消息什么时候送达到,订阅这个消息的订阅者需要给RabbitMQ
一个可执行的操作。我们通过传递一个订阅代理:
bus.Subscribe<MyMessage>("my_subscription_id", msg => Console.WriteLine(msg.Text));
- 1
现在每一次MyMessage
实例被发送后,EasyNetQ
将会调用我们的代理,打印这个消息的Text
属性到控制台。
你传给订阅的订阅Id
是重要的。 EasyNetQ
将会在RabbitMQ Broker
上为特定的消息类型的和订阅id
的组合创建唯一的队列。
每一次调用Subscribe
方法会创建一个新的队列消费者。如果你用相同的消息和订阅id
调用Subscribe
两次,你将会创建两个消费者去消费同一个队列。然后RabbitMQ
将会依次连续轮询消息给每一个消费者。这种可伸缩性和工作分担是非常棒的。比如说,你创建了一个处理特殊消息的服务,但是他已经超负荷工作了。简单的创建一个新的服务实例(在同一个机器上,或者不同的机器上),不用配置任何东西,你自动就得到了伸缩性。
假如相同的消息类型,用不同的订阅id
调用了两次Subscribe
,你将创建两个队列,每一个队列有自己的消费者。每一个消息的副本将会路由到每一个队列,因此不同的消费者都将得到所有消息(这个类型的)。假如你有几个不同的服务都关心相同类型的消息,这这样很好。
写订阅回调委托时的注意事项
通过EasyNetQ
订阅到一个来至队列的消息,他们被放置在内存队列中。一个单独线程循环对垒得到消息,调用他们的委托方法。因为在一个独立线程上一个委托一次处理一个消息,你应该避免长时间的同步的IO
操作。应该尽快从委托返回控制。
使用异步订阅 SubscribeAsync
SubscribeAsync
允许你的订阅者委托到一个能立即返回的Task
,然后异步的执行长时间IO
操作。一但长时间运行的订阅完成后,就简单的完成这个任务。下面的例子,我们请求一个web service
使用一个异步IO
操作(DownloadStringTask
)。当这个task
完成事,写一行信息到控制台。
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(() =>
{
//这里执行一些操作
//如果这里有一个异常,那么在这个Task执行完毕后,这个异常会作为结果返回,
// 然后任务将继续执行下去。
}).ContinueWith(task =>
{
if ( task.IsCompleted && ! task.IsFaulted)
{
// 一切都很好
}
else
{
// 不要Catch 异常,否则异常会进一步被嵌套,结果会被发送到默认的错误队列
throw new EasyNetQException("Message processing exception - look in t the default error quenue(broker)");
}
}));
取消订阅
所有的订阅都会返回一个ISubscriptionResult
接口实例。它包含属性有订阅底层被IConsumer
使用的IExchane
和IQueue
,如果你需要使用更高级的API IAdvancedBus
更好的去处理,这会变为可能。
你能够在任何时间取消一个订阅者,通过调用ISubscriptionResult
实例上的Dispose
方法,或者在它之上的 ConsumerCancellation
属性。
var subscriptionResult = bus.Subscribe<MyMessage>("sub_id", MyHandler);
...
subscriptionResult.Dispose();
// 这个等价与 subscriptionResult.ConsumerCancellation.Dispose();
这将停止EasyNetQ
对队列的消费,并且关闭这个消费者的channel
。
注意:IBus
和IAndvancedBus
的dispose
,可能够取消所有消费者,并关闭对RabbitMQ
的连接。
不要在消息处理器中调用 subscriptionResult.Dispose()
。这将在EasyNetQ ACK
消息时,在消费者的channel
和subscriptionResult.Dispose()
调用关闭Channel
之间,创建一个竞争状态。由于EasyNetQ
的内部架构这些将会在不同的线程被调用,还有时间上的不确定性。
EasyNetQ使用(三)【Publish与Subcribe】的更多相关文章
- RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现)
RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现) 在上一个教程中,我们创建了一个工作队列. 工作队列背后的假设是,每个任务都恰好交付给一个worker处理. 在这 ...
- Jenkins的使用(三)-------Publish over SSH和Publish over FTP
七.构建后操作 1.使用Publish over SSH 1.左边菜单栏 Manage Jenkins --->ManagePlugins--->可选插件,然后搜索 Publish ...
- C# .net 使用rabbitmq消息队列——EasyNetQ插件介绍
EasyNetQ 是一个简洁而适用的RabbitMQ .NET类库,本质上是一个在RabbitMQ.Client之上提供服务的组件集合.
- 使用jmeter对ActiveMQ集群性能方案进行评估--转载
原文地址:http://www.51testing.com/html/78/23978-143163.html 1.测试概要1.1 关于这篇文档中涉及的基于JMS的消息系统能为应用程序提供可靠的,高性 ...
- RabbitMQ教程总结
[译]RabbitMQ教程一 主要通过Hello Word对RabbitMQ有初步认识 [译]RabbitMQ教程二 工作队列,即一个生产者对多个消费者 循环分发.消息确认.消息持久.公平分发 [译] ...
- 消息队列面试题、RabbitMQ面试题、Kafka面试题、RocketMQ面试题 (史上最全、持续更新、吐血推荐)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- RabbitMQ(三) -- Publish/Subscribe
RabbitMQ(三) -- Publish/Subscribe `rabbitmq`支持一对多的模式,一般称为发布/订阅.也就是说,生产者产生一条消息后,`rabbitmq`会把该消息分发给所有的消 ...
- 【EasyNetQ】- 使用Future Publish调度事件
许多业务流程要求在将来某个日期安排事件.例如,在与客户进行初次销售联系后,我们可能希望在将来的某个时间安排跟进电话.EasyNetQ可以通过其Future Publish功能帮助您实现此功能.例如,这 ...
- EasyNetQ使用(七)【发布者确认 ,用Future Publish发布预定中事件 】
AMQP发布消息默认情况下是非事务性的,不能确保你的消息真正送达代理.AMQP可以去指定事务性发布,但是RabbitMQ这样会非常慢,我们没有让EasyNetQ API去支持此功能.为了高效的确保投递 ...
随机推荐
- 【基础数位DP-模板】HDU-2089-不要62
不要62 Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): Accepted Su ...
- 2.webpack最基本的使用方式
什么是webpack? webpack是前端的一个项目构建工具,它是基于Node.js开发出来的一个前端工具: webpack安装的两种方式 1.运行 'npm i webpack -g' 全局安装w ...
- Codeforces Round #585 (Div. 2) A. Yellow Cards(数学)
链接: https://codeforces.com/contest/1215/problem/A 题意: The final match of the Berland Football Cup ha ...
- BZOJ 4807 車 组合数学
思路:高精度\((what)\) 提交:2次(后来发现有种更快的写法) 题解: 设\(n>m\),那么显然答案为\(C(n,m)\),相当于只能放\(m\)个棋子,可以在\(n\)列中选任意不同 ...
- 018_查看有多少远程的 IP 在连接本机(不管是通过 ssh 还是 web 还是 ftp 都统计)
#!/bin/bash#使用 netstat -atn 可以查看本机所有连接的状态,-a 查看所有,-t 仅显示 tcp 连接的信息,-n 数字格式显示# Local Address(第四列是本机的 ...
- SharePoint學習
1.SharePoint 2010 Products -> SharePoint 2010 Products Configuration Wizard 配置好后,系統會自動在localho ...
- springBoot怎样访问静态资源?+静态资源简介
1.静态资源 怎样通过浏览器访问静态资源? 注意:不需要加static目录.因为只是告诉springboot目录,而不是静态资源路劲. 这时访问路径就需要加上/static
- 第2组 Alpha冲刺(4/4)
队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:了解整个游戏的流程 GitHub签入记录 接下来的计划:继续完成游戏 还剩下哪些任务:完成游戏 燃尽图 遇到的困难:没有美术比较好的 ...
- Nginx 之负载均衡与反向代理
负载均衡服务器策略: 1.轮循 每个请求逐个分发到后端服务器 2.加权轮循 按照分配的权重将请求分发到后端服务器 3.ip hash 轮询的基础上,保持一个客户端多次请求分发到一台后端服务器上 一 ...
- 解决Android Studio 打开Flutter 项目,找不到设备的问题
开始设置了ANDROID_HOME环境变量后,发现Flutter 识别不了安卓SDK, 使用命令配置发现配置是失败的,貌似是不支持路径里有空格 复制一份SDK到没有空格的路径后,SDK就能识别了,并且 ...