背景:
隨着社會的發展,經濟的飛躍,傳統的單系統模式(webApp+DB)已經很難滿足業務場景的需要。企業系統開始不斷演化成多個子系統並存協作的局面。大大降低了系統間的耦合性,更重要的便於子系統的擴展、升級、維護等。
談到系統間的協作,目前常用兩種方式:
1、基於Http協議
通過客戶端發起的get、post請求,服務端接收request請求,處理請求,得到響應內容,通過網絡傳送到客戶端,由瀏覽器解析出一個可視化的頁面。

這種交互最大的優勢是實時性,通過HTTP請求連接各個子系統,從而跨服務器來完成一個完整的業務流程。缺點協議請求頭的信息較少,一般都是關鍵參數,完整數據由下一個子系統從數據庫、文件系統來獲取,從來保證前后的業務數據銜接。
2、基於消息的模式。
這種模式一個很重要前提是對實時性要求不高。優點可以有效降低模塊的耦合性,減輕主干業務流程,將大量的業務交由后台任務來處理,有效縮短系統響應時間,提高系統TPS。
比如用戶下單成功后發送郵件功能,屬於非主干功能,完全可以從下單的主干業務邏輯剝離出來,從來提高下單的響應速度。而發送郵件的功能則由郵件服務器接收異步消息來跟蹤處理,帶有點分布式集群的感覺,
將一個任務有效拆分到多台服務器來完成。

所謂消息本質上是一種數據結構(當然,對象也可以看做是一種特殊的消息),它包含生產者與消費者雙方都能識別的數據,這些數據需要在不同的服務器之間進行傳遞,並可能會被多個完全不同的客戶端消費。

消息隊列降低了生產者和消費者之間的耦合性,他們不會存在直接的代碼依賴,方便各自的擴展,比如生產者因為業務下線,導致代碼下線,而消費端不用同時跟進處理,只是隊列不會有消息,這樣方便於更加靈活的協調開發資源,而不必一方下線,所有的依賴全部受影響,產生較高維護成本。另外我們也可以隨意對生產者和消費者擴展,引入多個消息隊列,他們之間的依賴可以配置在XML文件中,通過JNDI來獲取消息隊列Queue,每次加載時,通過lookup服務首先通過讀取配置文件來獲取通道。
常見的消息模型分為:點對點模型;發布-訂閱模型
點對點模型:Point to Point,消息被生產者放到一個隊列中,消費者從消息隊列中取走消息。消息一旦被一個消費者取走后,消息就從隊列中移除。這意味着即使有多個消費觀察一個隊列,但一個消息只能被一個消費者取走。
發布-訂閱模型:Publish/Subscribe,發布者發布一條消息可以發送給所有的訂閱用戶,所有的訂閱用戶都有處理某一條消息的機會。

對於訂閱者而言,有兩種處理消息的方式。一種是廣播機制,這時消息通道中的消息在出列的同時,還需要復制消息對象,將消息傳遞給多個訂閱者。例如,有多個子系統都需要獲取從CRM系統傳來的客戶信息,並根據傳遞過來的客戶信息,進行相應的處理。此時的消息通道又被稱為Propagation通道。另一種方式則屬於搶占機制,它遵循同步方式,在同一時間只能有一個訂閱者能夠處理該消息。實現Publisher-Subscriber模式的消息通道會選擇當前空閑的唯一訂閱者,並將消息出列,並傳遞給訂閱者的消息處理方法。
目前使用較多的是廣播機制的消息處理方式,且將topic與queue有效組合
一個生產消息的事件對應一個topic,topic下面可以掛多個queue,當然一個queue也可以掛在多個topic下面,每個queue都對應一個消息的消費端,唯一消費,保證消費的准確性。
如下圖所示,當下單時,會將下單的相關信息封裝到消息體中,發送到下單事件關聯的那個topic1中,然后Topic會將消息復制發送到掛載在其下面的所有隊列上,將Message復制到快照隊列、成交記錄統計隊列中,消息端會監聽隊列,
如果有消息 ,則啟動任務線程,來進行相關的業務處理。

在引入消息隊列時重點要注意以下幾點:
- 並發:選擇的消息隊列一定要很好地支持用戶訪問的並發性;
- 安全:消息隊列是否提供了足夠的安全機制;
- 性能伸縮:不能讓消息隊列成為整個系統的單一性能瓶頸;
- 部署:盡可能讓消息隊列的部署更為容易;
- 災備:不能因為意外的錯誤、故障或其他因素導致處理數據的丟失,最好可以寫入磁盤,持久化存儲;
- API易用性:處理消息的API必須足夠簡單、並能夠很好地支持測試與擴展
- 容量:隊列的容量一定要大,至少可以存儲千萬級別的消息體
目前市場上有很多成熟的消息框架:如Active MQ,IBM 的MQ,JBoss MQ,MSMQ等,各有各的優勢,在使用前一定要充分衡量是否可以滿足自己的業務需求