声明

本文欢迎转载,系博主原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7654902.html


前言

此文章,是承接上篇:【框架学习与探究之消息队列--EasyNetQ(1)】未完待续篇,依然对消息队列及其应用的一个补充说明和一些博主的见解。这里说一点废话:就博主自身所见而言的话还有后面了解,现在招聘说明当中部分虽然没有明确提出关于消息队列方面的需求,但是面试官看见几年工作经验的你肯定会多多少少问问关于对此的认识和见解,所以当你以一种颇为了解与实战的姿态说出自己的看法的时候,相信肯定会对这场面试的你加分不少的呐,从而也说明了现今开发当中消息队列的重要性,说到底,它RabbitMQ/EasyNetQ如果能给你带来加分的筹码以及薪资的提升,学习它何乐而不为呐!!!或许这就是面向工资编程吧!!


继续EasyNetQ文档划重点与测试

这里再次强调在基于系统之间的消息交互开发方面,尤其需要注意的就是消息的Publish/Consumer的两种操作的强制落地的思考与解决方案,博主在上文做出一定的见解和实际操作方案。

4、关于交换机的Type以及命名、消息队列的命名

这里如果使用了EasyNetQ框架的情况下(如其名字一样为了简单使用使用了约束),框架会产生如下约束:1、发布订阅的消息必须是.NET Class类型,且类似与DTO一样Public访问修饰符和默认的构造函数没有方法 2、根据消息的类型来进行路由选择。这里首先要说明的是,交换机的名字默认情况就是:因为上面的约定,所以例如当我们的消息定义为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; }
}

但是这里一般情况博主认为,就如同代码就是最好的注释一样,让消息类型作为消息队列的名字也是一种不错的解决方案,有一种自圆其说的感觉,从而也印证了框架作者如出一辙的想法就是采用消息类型路由的做法


5、主题路由与消息过滤

这里主要就是交换机的类型了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来绑定交换机才足以实现消息可以根据自定规则投递到对应的队列当中去


6、自动订阅者划重点

这里EasyNetQ,可以使用它来轻松扫描实现IConsume 或IConsumeAsync 的接口的类的特定程序集,然后自动将这些消费者订阅到RabbitMQ中去。 IConsume 的实现将使用总线Subscribe方法,而IConsumeAsync 的实现将使用总线SubscribeAsync方法。

1、一个消费者可以实现多个泛型消费接口或者异步的泛型消费接口,就可以实现承担消费多种类型的消息的功能

2、[ForTopic("Topic.Foo")]使用该标签在 实现类的方法上面就可以实现与普通订阅使用withtopic同样的效果

3、[AutoSubscriberConsumer(SubscriptionId = "MyExplicitId")] 为消费者对应的队列名称后缀

4、通过控制 AutoSubscriber 的构造函数的 GenerateSubscriptionId 就可以实现全局自动订阅者的配置项 、ConfigureSubscriptionConfiguration 实现全局消费者的配置

5、[SubscriptionConfiguration(CancelOnHaFailover = true, PrefetchCount = 10)] 控制消费者配置,作用于实现类的方法上面

6、替换 AutoSubscriber 的 MessageDispatcher 可以实现我们自定义消费者生产逻辑


总结

**通过第二篇文章我们再一次了解了如何通过框架去了解RabbitMq,以及使用和注意事项,当然这个离我们正真使用到项目集成到系统当中去还有一定的距离,不过相信阅读了这两篇文章的园友,应该还是有所收获,这里博主不光光是只是对框架做了一定的分许和解读,主要还是对rabbitmq本身一些注意点和特性机制做了一定实验研究,也从消息落地方面做了一定设想,这样在改善现有系统和以后新系统的搭建的时候能够做到心中有数的话也是起到了一定的作用了。这里抛出两个问题,也是博主后续将会去了解,1、就目前而言项目中发生了,消息的无故重发,因为隔离了系统的耦合性,导致消息内容一致却被重复处理的问题?提示:做到消息内容处理的幂等验证,不能依赖发送方的可靠性 2、关于如何搭建集群的rabbitmq服务与使用easynetq访问?集群搭建上文有参考链接,这里给出easynetq关于cluster support参考链接:https://github.com/EasyNetQ/EasyNetQ/wiki/Cluster-Support **

如果上述内容对您来说有一定作用的话,您的点赞和评论都是对博主最大的支持的呐,O(∩_∩)O嗯!

【框架学习与探究之消息队列--EasyNetQ(2)】的更多相关文章

  1. 【框架学习与探究之消息队列--EasyNetQ(1)】

    前言 本文欢迎转载,实属原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7603554.html 废话 既然都是废话了,所以大家就可以跳过了,这里是博主有事没事 ...

  2. 深入剖析 RabbitMQ —— Spring 框架下实现 AMQP 高级消息队列协议

    前言 消息队列在现今数据量超大,并发量超高的系统中是十分常用的.本文将会对现时最常用到的几款消息队列框架 ActiveMQ.RabbitMQ.Kafka 进行分析对比.详细介绍 RabbitMQ 在 ...

  3. enode框架step by step之消息队列的设计思路

    enode框架step by step之消息队列的设计思路 enode框架系列step by step文章系列索引: enode框架step by step之开篇 enode框架step by ste ...

  4. 【框架学习与探究之宿主服务--Topshelf】

    前言 此文欢迎转载,原始链接地址:http://www.cnblogs.com/DjlNet/p/7603819.html 正文 原先也偶然见过这个关键词,当时只是有个大致了解貌似和WinServic ...

  5. 【框架学习与探究之定时器--Hangfire】

    声明 本文欢迎转载,请注明文章原始出处:http://www.cnblogs.com/DjlNet/p/7603632.html 前言 在上篇文章当中我们知道关于Quartz.NET的一些情况,其实博 ...

  6. 【框架学习与探究之日志组件--Log4Net与NLog】

    前言 本文欢迎转载,作者原创地址:http://www.cnblogs.com/DjlNet/p/7604340.html 序 近日,天气渐冷,懒惰的脑虫又开始作祟了,导致近日内功修炼迟迟未能进步,依 ...

  7. Redis学习之实现优先级消息队列

    很久没有写博客了,最近简单的学习了一下Redis,其中学习了一下用Redis实现优先级消息队列.关于更多更为详细的可以在www.redis.cn找到相关资料. 对于熟悉Redis的童鞋提到队列很自然的 ...

  8. C# .net 使用rabbitmq消息队列——EasyNetQ插件介绍

    EasyNetQ 是一个简洁而适用的RabbitMQ .NET类库,本质上是一个在RabbitMQ.Client之上提供服务的组件集合.

  9. 【框架学习与探究之定时器--Quartz.Net 】

    声明 本文欢迎转载,原文地址:http://www.cnblogs.com/DjlNet/p/7572174.html 前言 这里相信大部分玩家之前现在都应该有过使用定时器的时候或者需求,例如什么定时 ...

随机推荐

  1. CCNA+NP学习笔记—交换网络篇

    本章关于企业网络的最底层--交换层,难度较低,主要为以后三层的路由做铺垫.所有笔记的分类顺序为:序章→交换层→路由层→运营商,体现了从企业网到互联网的学习顺序. 注:思科设备命令行通常不分大小写!以后 ...

  2. alert执行顺序

    <p><span id="span1">Hello World!</span></p> <script type=" ...

  3. 团队作业8——第二次项目冲刺(Beta版本)5.24

    1.当天站立式会议照片 会议内容 1.总结前几次会议中出现的问题. 2.对第二天需要做的任务进行分配. 3.询问团队队员任务完成情况以及时间分配是否充分. 4.对今后的任务,发表自己的看法. 2.每个 ...

  4. 【Beta阶段】计划安排

    一.新成员介绍 姓名    陈雄 学号    106 角色    前端 个人相片     二.完善功能 登录注册 记分板 排行榜 界面优化 三.新增功能 换肤(可以一试) 联网PK 分享邀请 四.团队 ...

  5. 201521123019 《Java程序设计》第12周学习总结

    1. 本章学习总结 2. 书面作业 Q1.字符流与文本文件:使用 PrintWriter(写),BufferedReader(读) 1.1 生成的三个学生对象,使用PrintWriter的printl ...

  6. 201521123104 《Java程序设计》 第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  7. Lucene第二篇【抽取工具类、索引库优化、分词器、高亮、摘要、排序、多条件搜索】

    对Lucene代码优化 我们再次看回我们上一篇快速入门写过的代码,我来截取一些有代表性的: 以下代码在把数据填充到索引库,和从索引库查询数据的时候,都出现了.是重复代码! Directory dire ...

  8. SQL 常用语法一

    整理笔记,并将常用的SQL语法记录下来. 这些方法有 CASE WHEN, IFNULL,GROUP BY,LIMIT,SUBSTR 1,字段转换 CASE WHEN 意义: If(a==b) a=c ...

  9. Thinkphp5.0 在自己定义一个公共方法的控制器并且继承了Controller类的时候报错

    在建立网站的时候,你通常想着把一些共有的方法提取出来,放入一个控制器内,如果你是将业务逻辑写入了构造函数里面,那么就得注意了. 在thinkphp5.0当中,有一个初始化的方法,类似于构造函数,那就是 ...

  10. 读Zepto源码之Gesture模块

    Gesture 模块基于 IOS 上的 Gesture 事件的封装,利用 scale 属性,封装出 pinch 系列事件. 读 Zepto 源码系列文章已经放到了github上,欢迎star: rea ...