本文欢迎转载,系博主原创,本文原始连接地址:http://www.cnblogs.com/DjlNet/p/7654902.htmlhtml
此文章,是承接上篇:【框架学习与探究之消息队列--EasyNetQ(1)】未完待续篇,依然对消息队列及其应用的一个补充说明和一些博主的看法。这里说一点废话:就博主自身所见而言的话还有后面了解,如今招聘说明当中部分虽然没有明确提出关于消息队列方面的需求,可是面试官看见几年工做经验的你确定会多多少少问问关于对此的认识和看法,因此当你以一种颇为了解与实战的姿态说出本身的见解的时候,相信确定会对这场面试的你加分很多的呐,从而也说明了现今开发当中消息队列的重要性,说到底,它RabbitMQ/EasyNetQ若是能给你带来加分的筹码以及薪资的提高,学习它何乐而不为呐!!!或许这就是面向工资编程吧!!git
这里再次强调在基于系统之间的消息交互开发方面,尤为须要注意的就是消息的Publish/Consumer的两种操做的强制落地的思考与解决方案,博主在上文作出必定的看法和实际操做方案。github
这里若是使用了EasyNetQ框架的状况下(如其名字同样为了简单使用使用了约束),框架会产生以下约束:一、发布订阅的消息必须是.NET Class类型,且相似与DTO同样Public访问修饰符和默认的构造函数没有方法 二、根据消息的类型来进行路由选择。这里首先要说明的是,交换机的名字默认状况就是:由于上面的约定,因此例如当咱们的消息定义为public class TextMessage{}
的时候,那么默认状况所产生交换机的名字就是:Messages.TextMessage:Messages
(类型的全名称:程序集的名字)而且Exchange类型指定为了Topic,这里须要说明一下就是在几种交换机类型当中,Topic是最灵活能够变相的经过它实现其余类型的工做方式,因此咱们的EasyNetQ直接指定该工做类型为了简单化的使用原则;接下来在消费者去订阅该消息的时候默认状况产生队列的名字就是:Messages.TextMessage:Messages_{YourSubscriptionId}
这里YourSubscriptionId能够为empty那么产生的队列名字就会与交换机同名了。面试
那么框架这里提供这个YourSubscriptionId玩意儿给使用者是干嘛使用的呐?编程
这里博主的理解就是有这个功能点的实现,多半是有这方面的需求,例如当咱们须要一个交换机绑定多个队列,可是使用的消息格式是同一个.NET类型,这里就可以使用自定义的SubscriptionId来实现多队列多消费者模式,例如日志分发消息系统的需求,也能够当这个标记符来当作相似与模块或者系统的标记达到一看见队列的名字就知道消费者的建立者,等等一些具备意义的标记,切记注意最大字符个数225,还有一点就是如何实现工做队列模式?这里只须要重复订阅同一个消息类型且SubscriptionId一致便可实现多个消费者对同一个队列的共同消费模式,例如当出现既有的消费者已经知足不了处理效率支持的状况下,可是又不想改动原先系统的状况,就能够实现无痛式的增长一个消费者来共同消费达到负载均衡的效果,以及诸如此类的场景。注意:当订阅者消息类型一致的时候,SubscriptionId不一样的话就会造成消息复制分发的效果
固然拉,若是想实现更改默认的框架约束自定义交换机和队列名字,参考以下(博主实验证实可行):安全
[Queue("TestMessagesQueue", ExchangeName = "MyTestExchange")] public class TestMessage { public string Text { get; set; } }
可是这里通常状况博主认为,就如同代码就是最好的注释同样,让消息类型做为消息队列的名字也是一种不错的解决方案,有一种自圆其说的感受,从而也印证了框架做者一模一样的想法就是采用消息类型路由的作法负载均衡
这里主要就是交换机的类型了Topic使用了,这里具体的解释与使用参考第一篇文中给出的地址,这里博主须要说明的是框架中注意点:当多个消费者指定了相同的消息类型且指定相同的SubscriptionId,那么这些消费者就算是指定了本身的WithTopic也不会达到消息过滤的效果,由于Topic的RouteKey是做用于交换机与队列的不是消息自己,那么既然消费者们都已是消费同一个队列了那确定就不会产生消息的过滤了。框架
那么在此框架中提供topic有什么其余用途么,我该怎么使用呐?异步
这里咱们依然采用举例子(固然可能例子有些牵强为了迎合咱们的topic功能点)的方式来讲明,假设咱们如今有性能监控系统(A)、日志处理报警系统(B),这里咱们其余应用系统底订单系统、库存系统、财务系统等产生的性能安全错误相关消息日志都会通通就发送到A,而后由A分析和挑选出须要转发到B的消息以LogInfoMessage的方式统一推送到MQServer当中,这里使用了同一个消息类型就意味着同一个交换机,这里Publish的时候根据不一样携带了不一样的RouteKey,例如订单系统->Order.Create、Order.Cancel等等,库存系统->Inventory.Adjust、Inventory.Delivery等等,诸如此类的路由键,而后假设咱们的B系统有LogInfoMessage的消费者们,它们可能并不须要关心全部的日志消息,例如OrderLogInfoMessageConsumer只关心订单相关的,配置为 WithTopic("Order.#"),相似InventoryLogInfoMessageConsumer只关心库存相关的日志,配置为了 WithTopic("Inventory.#"),且消费者须要指定惟一的标识,这样一来将会造成一个交换机绑定了多个多个队列以及各自的消费者们,具体参考以下:
上图是关于RabbitMQ交换机的bindings配置图也说说明了问题,这样一来就能够实现同一个消息类型也能够实现消息的按需求过滤式消费了,参考配置对应代码:
例子发布者代码如图:
例子消费者代码以下:函数
bus.Subscribe<LogInfoMessage>(string.Empty, x => Console.WriteLine(x.Body + " " + x.Creator)); bus.Subscribe<LogInfoMessage>("Order", x => Console.WriteLine(x.Body + " " + x.Creator), x => x.WithTopic("Order.#")); bus.Subscribe<LogInfoMessage>("Inventory", x => Console.WriteLine(x.Body + " " + x.Creator), x => x.WithTopic("Inventory.#")); bus.Subscribe<LogInfoMessage>("Finance", x => Console.WriteLine(x.Body + " " + x.Creator),x => x.WithTopic("Finance.#")); bus.Subscribe<LogInfoMessage>("Order_Inventory", x => Console.WriteLine(x.Body + " " + x.Creator),x => x.WithTopic("Order.#").WithTopic("Inventory.#"));
以上例子便展现topic的应用场景和使用规则,这与上面讲到的SubscriptionId有必定关系,它产生了不一样的队列才得以实现不一样的队列用不一样的routekey来绑定交换机才足以实现消息能够根据自定规则投递到对应的队列当中去。
这里EasyNetQ,可使用它来轻松扫描实现IConsume
一、一个消费者能够实现多个泛型消费接口或者异步的泛型消费接口,就能够实现承担消费多种类型的消息的功能
二、[ForTopic("Topic.Foo")]使用该标签在 实现类的方法上面就能够实现与普通订阅使用withtopic一样的效果
三、[AutoSubscriberConsumer(SubscriptionId = "MyExplicitId")] 为消费者对应的队列名称后缀
四、经过控制 AutoSubscriber 的构造函数的 GenerateSubscriptionId 就能够实现全局自动订阅者的配置项 、ConfigureSubscriptionConfiguration 实现全局消费者的配置
五、[SubscriptionConfiguration(CancelOnHaFailover = true, PrefetchCount = 10)] 控制消费者配置,做用于实现类的方法上面
六、替换 AutoSubscriber 的 MessageDispatcher 能够实现咱们自定义消费者生产逻辑
经过第二篇文章咱们再一次了解了如何经过框架去了解RabbitMq,以及使用和注意事项,固然这个离咱们正真使用到项目集成到系统当中去还有必定的距离,不过相信阅读了这两篇文章的园友,应该仍是有所收获,这里博主不光光是只是对框架作了必定的分许和解读,主要仍是对rabbitmq自己一些注意点和特性机制作了必定实验研究,也从消息落地方面作了必定设想,这样在改善现有系统和之后新系统的搭建的时候可以作到心中有数的话也是起到了必定的做用了。这里抛出两个问题,也是博主后续将会去了解,一、就目前而言项目中发生了,消息的无端重发,由于隔离了系统的耦合性,致使消息内容一致却被重复处理的问题?提示:作到消息内容处理的幂等验证,不能依赖发送方的可靠性 二、关于如何搭建集群的rabbitmq服务与使用easynetq访问?集群搭建上文有参考连接,这里给出easynetq关于cluster support参考连接:https://github.com/EasyNetQ/EasyNetQ/wiki/Cluster-Support
若是上述内容对您来讲有必定做用的话,您的点赞和评论都是对博主最大的支持的呐,O(∩_∩)O嗯!