EasyNetQ使用(九)【非泛型的发布&订阅扩展方法,发生错误的情况 】
自从EasyNetQ
第一个版本开始,它就可以发布/订阅特定类型的消息。
bus.Subscribe<MyMessage>("subscriptionId",
x => Console.WriteLine(x.Text));
bus.Publish<MyMessage>(theMessage);
但是,在运行期间,你怎么去发现消息类型?例如:你可能有一些系统加载外部插件,希望能订阅他们自己的消息类型。EasyNetQ为了这个目标提供了非泛型的发布和订阅方法。
只要加上这个using语句:
using EasyNetQ.NonGeneric;
它将提供给你一些subscription扩展方法。
public static IDisposable Subscribe(
this IBus bus,
Type messageType,
string subscriptionId,
Action<object> onMessage)
public static IDisposable Subscribe(
this IBus bus,
Type messageType,
string subscriptionId,
Action<object> onMessage,
Action<ISubscriptionConfiguration> configure)
public static IDisposable SubscribeAsync(
this IBus bus,
Type messageType,
string subscriptionId,
Func<object, Task> onMessage)
public static IDisposable SubscribeAsync(
this IBus bus,
Type messageType,
string subscriptionId,
Func<object, Task> onMessage,
Action<ISubscriptionConfiguration> configure)
还包括发布扩展方法:
public static void Publish(
this IBus bus,
Type messageType,
object message)
public static void Publish(
this IBus bus,
Type messageType,
object message,
string topic)
public static Task PublishAsync(
this IBus bus,
Type messageType,
object message)
public static Task PublishAsync(
this IBus bus,
Type messageType,
object message,
string topic)
它们就像IBus
上的Publish
和Subscribe
方法一样,除了提供一个Type参数,作为泛型参数的替代,消息处理器用Action替代了Action。
var messageType = typeof(MyMessage);
bus.Subscribe(messageType, "my_subscriptionId", x =>
{
var message = (MyMessage)x;
Console.Out.WriteLine("Got Message: {0}", x.Text);
});
这里有一个例子,使用了非泛型的Publish。
var messageType = typeof(MyMessage);
bus.Publish(messageType, theMessage);
这一篇文章让我们看看在消息系统中可能发生的各种错误的情况下,看下EasyNetQ
如何处理它们。
订阅服务挂了
当你写了一个windows
服务,用来订阅一个NewCustomerMessage
消息。
如果这个服务失败时会发生什么呢?为了效率,EasyNetQ
为订阅功能实现了一个基于内存的内部使用的队列。消息通过网络从RabbitMQ中接收到后,会把消息放到这个内存队列中。一个订阅者线程从这个内存队列拿走消息后,回调自己提供的消息处理代码。一旦这个回调完成后,EasyNetQ
会发送'Ack'
给RabbitMQ
。没有收到'Ack'
前,这个消息不会从RabbitMQ
消息队列中被删除。如果你的服务在处理这个消息时挂掉了,这个消息(所有的消息都在EasyNetQ
内存队列中)仍将呆在RabbitMQ
队列中。直到你的服务再次连接上后,这些消息将会再次被发送。
我的订阅者消费消息的速度比消息发布速度慢
EasyNetQ
利用了RabbitMQ
服务的特性,设置prefetch-count
值为一个比较可用的值(当前是50).这意味着,将最多不会超过50条消息在消费者的内存队列中。这样会防止在你的正在订阅的应用发生内存超出异常。一旦未Ack
消息数累积到这个值后,RabbitMQ
将停止发送消息,只是保留这些消息在EasyNetQ
的内存队列中。当然,最终这个队列将会吃掉你的RabbitMQ
服务器上的所有磁盘空间。你应该在这个地方做下监控,确保在发生这种情况发生前你能够得到警报。
在我的订阅者和RabbitMQ代理之间发生网络故障
如前面文章用EasyNetQ
连接RabbitMQ
所述,EasyNetQ
实现了一个延迟连接策略。这个策略假设这个代理不会总是可用的。当你第一次通过使用RabbitHutch.CreateBus
连接到这个代理时,EasyNetQ
开启一个连接,不断循环尝试去连接代理,如果你指定的连接字符串地址的代理没有处于可用状态,你会从消息信息日志中看到'Trying to Connect'
。订阅者能够使用bus.Subscribe
方法去订阅,即使当这个代理不可用时。这个订阅的细节会被EasyNetQ
缓存。 当代理恢复可用时,这个正在不断循环尝试连接将会成功连接到代理,并且所有缓存的订阅一同恢复。
同样,当EasyNetQ
和代理连接中断时,它将返回到循环连接,你在日志中看'Trying to Connect'
信息。一旦连接重新建立,被缓存的订阅者将再次被建立。最后结论就是,在正在运行环境中,无论在网络断开时,或是你需要在被你的RabbitMQ
代理拒绝时,你能够保留你的订阅者。
当消费一个消息时,订阅回调抛出异常
如果你的订阅回调抛出异常,EasyNetQ
将会拿到这个正在被消费的消息,包装这个消息到一个指定错误消息中。这个错误消息将会被发布到EasyNetQ
的错误队列(名字是EasyNetQ_Default_Error_Queue
)。你应该监控这个错误队列中的消息。这个错误消息包括所有必要的信息,例如需要重新发布的原始消息,以及异常的类型,异常信息和堆栈信息。你可能使用EasyNetQ.Hosepipe
工具重新发布错误信息。参考下一篇文章EasyNetQ.Hosepipe
EasyNetQ使用(九)【非泛型的发布&订阅扩展方法,发生错误的情况 】的更多相关文章
- 17-EasyNetQ:非泛型的发布&订阅扩展方法
自从EasyNetQ第一个版本开始,它就可以发布/订阅特定类型的消息. bus.Subscribe<MyMessage>("subscriptionId", x =&g ...
- Redis学习九:Redis的发布订阅
发布订阅功能,redis也具备,但是要知道的是redis主要功能还是分布式的缓存功能,因此这种订阅发布功能很少用,有专门的kafka activemq 等消息中间件来完成,因此本文只是简单介绍,了解 ...
- 开发创建XMPP“发布订阅”扩展(xmpp pubsub extend)
发布订阅(PubSub)是一个功能强大的XMPP协议扩展.用户订阅一个项目(在xmpp中叫做node),得到通知时,也即当事项节点更新时.xmpp服务器通知用户(通过message格式). 节点类型: ...
- 消息队列 ActiveMQ的简单了解以及点对点与发布订阅的方法实现ActiveMQ
Apache ActiveMQ是Apache软件基金会所研发的开放源代码消息中间件: 由于ActiveMQ是一个纯Java程序,因此只需要操作系统支持Java虚拟机,ActiveMQ便可执行. Act ...
- Redis发布订阅使用方法
Redis发布订阅 发布订阅模式中发布消息的为publisher即发布者,接收消息的为subscriber即订阅者.在Redis中,所有的消息通过channel即频道进行发布,一个发布者可以向多个ch ...
- SQL Server 2008 R2的发布订阅配置实践
纸上得来终觉浅,绝知此事要躬行.搞技术尤其如此,看别人配置SQL SERVER的复制,发布-订阅.镜像.日志传送者方面的文章,感觉挺简单,好像轻轻松松的,但是当你自己去实践的时候,你会发现还真不是那么 ...
- AKKA集群中的分布式发布订阅
集群中的分布式发布订阅 如何向一个不知道在哪个节点上运行的actor发送消息呢? 如何向集群中的所有actor发送感兴趣的主题的消息? 这种模式提供了一个中介actor,akka.cluster.pu ...
- Blazor+Dapr+K8s微服务之事件发布订阅
我们要实现的是:在blazorweb服务中发布一个事件,并传递事件参数,然后在serviceapi1服务中订阅该事件,接收到blazorweb服务中发布的事件和参数. 1 在blazo ...
- easynetq发布订阅demo实现注意事项
最近开始在项目中使用easynetq,大概了解了下api,在网上看了下示例,结果没有一个运行成功的,一个最简单的发布订阅都没有成功.我是直接运行起来别人的示例,不应该啊,后来一直分析一直分析,最后发现 ...
随机推荐
- appium问题汇总(持续更新。。。)
WEBVIEW_unknown adb版本较低,adb 1.0.32版本不支持安卓8.x版本,更新adb版本后正常 Install homebrew ruby -e "$(curl -fsS ...
- 重写Router.prototype.push后还报NavigationDuplicated错误的解决方法
vue项目路由跳转时控制台出现NavigationDuplicated错误, message: "Navigating to current location (XXX) is not ...
- 主席树K-th Number
/*K-th NumberTime Limit: 20000MS Memory Limit: 65536KTotal Submissions: 44535 Accepted: 14779Case Ti ...
- CSPS模拟86-87
模拟86 T1,烧水,按位统计贡献,利用某种sao操作避免数位dp #include<iostream> #include<cstdio> #include<cstrin ...
- 【原创】go语言学习(九)指针类型
目录 变量和内存地址 指针类型 值拷贝和引用拷贝 变量和内存地址 1.每个变量都有内存地址,可以说通过变量来操作对应大小的内存 var a int32 a = 100 fmt.Printf(“%d\n ...
- [bzoj 3566][SHOI 2014]概率充电器
传送门 Description SHOI 概率充电器由 n-1 条导线连通了 n 个充电元件.进行充电时,每条导线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率决定. 随后电能可以 ...
- Vuex学习心得
最近公司项目中使用Vuex做状态管理,就全面温习了一遍文档,然后在项目使用中遇到一些常见问题就一一总结下. 一.由来 我们知道Vue中数据是自顶向下单向流动的,但是以下两种情况单向数据流实现起来十分繁 ...
- sonca排除不扫描文件
在pom.xml文件中的<properties>标签下加上<sonar.exclusions>XXX</sonar.exclusions>标签,如下 <pro ...
- [CSP-S模拟测试]:跳房子(模拟)
题目描述 跳房子,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一.跳房子是在$N$个格子上进行的,$CYJ$对游戏进行了改进,该成了跳棋盘,改进后的游戏是在一个$N$行$M$列的棋盘上进行,并 ...
- Mysql之数据库设计规范
1. 三大范式首先要明白”范式(NF)”是什么意思.按照教材中的定义,范式是“符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度”.数据库范式也分为1NF,2NF,3NF,B ...