【NServiceBus】發佈和訂閱

發佈/訂閱  Publish/subscribe

在NServiceBus 的單向(one-way)通信模式中,消息的發送者往往無法知道接收者的詳細信息。實現這個額外的“鬆耦合”的代價是:訂閱者Subscriber 需要顯式的選擇接入,從而來接受特定消息。如下圖所示:

 

(1)      訂閱Subscription

訂閱者需要知道那個服務終端(Endpoint)負責特定的消息。這些信息通常放在契約Contract中,用於指定一個訂閱者應該把請求發給哪個終端。作爲“訂閱消息”的一部分,訂閱者傳遞了它的“返回地址return address”,用於告訴服務發佈者它希望接受消息的終端。

記住,服務發佈者終端會記住(存儲到DB)對每個事件消息感興趣的每個訂閱終端的地址。這種方式允許多臺發佈服務終端同時工作,而不用管哪臺服務終端是否受到了訂閱的消息。舉個例子:

【例子】PA,PB,PC三臺事件服務發佈者機器,使用一個數據庫DB1,那麼如果之前是PA收到了某個訂閱者subscriber1的訂閱請求,並且存入數據庫DB1,那麼當事件E1發生時,PA主機負載繁忙,這時候,PB或者PC都可以發佈該事件消息。

訂閱者沒必要自己去訂閱事件服務。通過使用“返回地址”的方式,一箇中心化的配置站點將發送多個訂閱消息到每一個事件發行者,這些消息中包含了“哪個訂閱者終端”訂閱了“哪個事件消息”。

另一方面,爲了讓多個 物理上的 訂閱者主機(PhysicalSubscriber)共同解決同一種事件,我們可以讓這多個訂閱者主機在邏輯上抽象爲單個邏輯訂閱者(Logical Subscriber)。這種方式還能讓均衡負載變爲可能,並且不需要在發佈者上或者訂閱者的代碼邏輯中去協調控制。實現了這種方案,這些訂閱者主機(物理上)只需要在訂閱信息中設置相同的“返回地址”,即邏輯訂閱者終端分配器的地址。

【注】普通情況下,我們均衡負載是在服務器上進行控制:讀取各個客戶端的狀態,挑選一個最小負載的客戶端,把任務發過去。或者是在客戶端程序中去控制。

 

(2)      發佈事件

     如下圖所示爲發佈的情況。



發佈一個事件消息意味着要把該事件消息通知到每一個訂閱了該事件的終端主機。

發佈的消息一般指事件,或者已經發生的事情。比如:訂單取消,產品下架,快遞延遲等。有時候,引發事件的原因正是處理了前面一條Command消息,比如取消訂單。取消訂單是Command,取消訂單的執行結果有成功和失敗,處理完畢後這將引發一個訂單取消事件,裏面記錄了事件以及最終的結果。發佈者不需要把事件發佈當作是處理Command消息的一部分(雖然這樣做很簡單)。爲什麼?因爲我們知道,Command消息的數量是很多的,如果在短時間內,對每個command都發布事件的話,那麼在訂閱者終端來說,會大大加重其接受負載。我們給出的方法是,發佈者根據特定頻率來檢查在該時間段內發送的所有改變,把這些改變打包成一個單一的事件消息,發送給訂閱者。頻率間隔的大小要根據業務不同來選擇,比如對於金融數據,那麼最好設置爲10ms,對於電子商務消費來說的話,1分鐘也是可以接受的。

【例子】如發佈者服務器終端在1s內接受到了來自Command請求者C1的1萬條請求,分別對某個訂單進行修改和取消,重新預定,那麼這1s內,訂閱者也會受到這1萬條事件消息。這樣不可行。正確的做法是,1s之後,服務器進行變更總結,把這些Command執行完畢後的最終改變打包爲一個事件消息,告訴訂閱者。

另一個定時發佈消息的好處是,處理某個Command消息的主機不一定是發佈時間消息的主機,這樣,主機的負載就可以被更好的均衡。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章