目錄編程
熟悉消息中間件的同窗應該對發佈/訂閱模式(Publish Subscribe Pattern)並不陌生。即便你不瞭解消息中間件,那麼在平時生活中發佈/訂閱模式也是很是常見的場景。設計模式
好比你打開你的微信訂閱號,你訂閱的做者發佈的文章,會廣播給每一個訂閱者。在這個場景裏,微信公衆號就是一個Pulisher,而你就是一個Subscriber,你收到的文章就是一個Message。安全
下面咱們就一塊兒瞭解一下發佈/訂閱模式
,若是你要了解並在本身的項目中使用這個模式,或者你對消息隊列(MQ)等中間件的原理感興趣,那麼這個系列的文章就是最高效地深刻淺出寶典。服務器
發佈/訂閱模式(Publish Subscribe Pattern)屬於設計模式中的行爲(Behavioral Patterns)。微信
在軟件架構中,發佈/訂閱是一種消息範式,消息的發送者(稱爲發佈者)不會將消息直接發送給特定的接收者(稱爲訂閱者),而是經過消息通道廣播出去,讓訂閱改消息主題的訂閱者消費到。架構
發佈/訂閱者模式
最大的特色就是實現了鬆耦合,也就是說你可讓發佈者發佈消息、訂閱者接受消息,而不是尋找一種方式把兩個分離的系統鏈接在一塊兒。固然這種鬆耦合也是發佈/訂閱者模式
最大的缺點,由於須要中間的代理,增長了系統的複雜度。並且發佈者沒法實時知道發佈的消息是否被每一個訂閱者接收到了,增長了系統的不肯定性。異步
發佈/訂閱者模式
的優勢發佈/訂閱者模式
的優勢能夠概括爲:編程語言
發佈/訂閱者模式
能夠將衆多須要通訊的子系統(Subsystem)解耦,每一個子系統均可以獨立管理。並且即便部分子系統下線了,也不會影響系統消息的總體管理。測試
發佈/訂閱者模式
爲應用程序提供了關注點分離。每一個應用程序均可以專一於其核心功能,而消息傳遞基礎結構負責將消息路由到每一個消費者手裏。設計
發佈/訂閱者模式
增長了系統的可伸縮性,並提升了發送者的響應能力。緣由是發送方(Publisher)能夠快速地向輸入通道發送一條消息,而後返回到其核心處理職責,而沒必要等待子系統處理完成。而後消息傳遞的基礎結構負責確保把消息傳遞到每一個訂閱者(Subscriber)手裏。
發佈/訂閱者模式
提升了可靠性。異步的消息傳遞有助於應用程序在增長的負載下繼續平穩運行,而且能夠更有效地處理間歇性故障。
你不須要關心不一樣的組件是如何組合在一塊兒的,只要他們共同遵照一份協議便可。
發佈/訂閱者模式
容許延遲處理或者按計劃的處理。例如當系統負載大的時候,訂閱者能夠等到非高峯時間才接收消息,或者根據特定的計劃處理消息。
發佈/訂閱者模式
提升了可測試性。通道能夠被監視,消息能夠做爲總體集成測試策略的一部分而被檢查或記錄。
發佈/訂閱者模式
須要考慮的點訂閱者能夠在消息通道中訂閱或者取消訂閱某個話題。
鏈接到任何消息通道必須受到安全策略的限制,以防止未經受權的用戶或應用程序竊聽。
根據每條消息的內容檢查和分發消息。每一個訂戶均可以指定其感興趣的內容。
訂閱者一般只對發佈者分發的消息的子集感興趣。消息服務一般容許訂戶縮小如下用戶接收到的消息集。
考慮容許訂戶經過通配符訂閱多個主題。每一個主題都有一個專用的輸出通道,每一個使用者均可以訂閱全部相關主題。
發佈訂閱系統中的通道被視爲單向的。
若是特定訂戶須要向發佈服務器發送確認或通訊狀態,請考慮使用請求/回覆模式。此模式使用一個通道向訂閱服務器發送消息,以及一個單獨的回覆通道向發佈服務器進行通訊。
使用者實例接收消息的順序不必定獲得保證,也不必定反映消息的建立順序。
設計該系統以確保消息處理是等量的,以幫助消除對消息處理順序的任何依賴。
有些解決方案可能須要按特定順序處理消息。優先級隊列模式提供了一種確保特定消息先於其餘消息傳遞的機制。
格式錯誤的消息或須要訪問不可用資源的任務可能會致使服務實例失敗。系統應防止此類消息返回到隊列,不然可能致使系統故障。
同一消息可能會發送屢次。例如,發送者可能在發佈消息後出現了異常,沒有記錄本身已經成功發送了消息,而後,發送者的新實例可能會啓動並重復該消息。
消息基礎結構應基於消息ID實現重複消息檢測和刪除(也稱爲重複數據消除),以便最多提供一次消息傳遞。
消息的生命週期可能有限。若是在這段時間內沒有處理,它可能再也不有價值,應該丟棄。發送方能夠指定過時時間做爲消息中數據的一部分。在決定是否執行與消息關聯的業務邏輯以前,接收者能夠檢查此信息,以確保消息沒有過時。
例如,消息可能會被暫時禁止,直到特定的日期和時間才被處理。
發佈/訂閱者模式
若是你的程序只有不多的訂閱者,或者須要與子系統進行實時的交互,那麼發佈/訂閱者模式
是不適合的。
在如下狀況下能夠考慮使用此模式:
應用程序須要向大量消費者廣播信息。例如微信訂閱號就是一個消費者量龐大的廣播平臺。
應用程序須要與一個或多個獨立開發的應用程序或服務通訊,這些應用程序或服務可能使用不一樣的平臺、編程語言和通訊協議。
應用程序能夠向消費者發送信息,而不須要消費者的實時響應。
被集成的系統被設計爲支持其數據的最終一致性模型。
應用程序須要將信息傳遞給多個消費者,這些消費者可能具備與發送者不一樣的可用性要求或正常運行時間計劃。例如你消息在上午發佈了出去,消費者計劃在下午纔去處理這些消息。
發佈/訂閱者模式
與觀察者模式
發佈/訂閱者模式
與觀察者模式
是咱們常常混淆的兩種設計模式,能夠說兩種設計模式在行爲上有必定的類似性,但倒是兩種不一樣的設計模式。或者說發佈/訂閱者模式
是觀察者模式
的一種變體。
經過下圖能夠清晰地看到兩種設計模式的不一樣點。
發佈/訂閱者模式
與觀察者模式
主要有如下幾個不一樣點:
在觀察者模式中,主體維護觀察者列表,所以主體知道當狀態發生變化時如何通知觀察者。然而,在發佈者/訂閱者中,發佈者和訂閱者不須要相互瞭解。它們只需在中間層消息代理(或消息隊列)的幫助下進行通訊。
在發佈者/訂閱者模式中,組件與觀察者模式徹底分離。在觀察者模式中,主題和觀察者鬆散耦合。
觀察者模式主要是以同步方式實現的,即當發生某些事件時,主題調用其全部觀察者的適當方法。發佈服務器/訂閱服務器模式主要以異步方式實現(使用消息隊列)。
發佈者/訂閱者模式更像是一種跨應用程序模式。發佈服務器和訂閱服務器能夠駐留在兩個不一樣的應用程序中。它們中的每個都經過消息代理或消息隊列進行通訊。
本文介紹了發佈者/訂閱者模式
的相關概念,後面幾篇會詳細介紹具體實現。