本文歡迎轉載,系博主原創,本文原始連接地址: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嗯!