初識消息中間件
維基百科上對於消息中間件的定義是"Message-oriented middleware(MOM) is software infrastructure focused on sending and receiving messages between distrubuted systems"。解釋起來就是消息中間件是在分佈式系統中完成消息的發送和傳遞的基礎軟件。看張圖來更直觀地理解消息中間件:
看到消息中間件有兩個好處:
1、異步
2、解耦
應用A和應用B都和消息中間件打交道,這兩個應用之間並不直接聯繫,這樣就完成了解耦,目的是希望收發消息的雙方彼此不知道對方的存在,也不受對方的影響,所以將消息投遞給接收者實際上都採用了異步的方式。
透過示例看消息中間件對應用的解耦
以蘋果的App Store爲例吧,App Store有一個功能:用戶充值成功後向用戶手機發送一條短信,算是一個安全選項。最直觀的,我們會這麼實現:
然後,我們需要把用戶付款的信息(用戶名、時間、IP等數據)傳給安全系統,安全系統會根據安全策略進行相關的判斷和處理,因此結構變成:
這麼看起來還好,那麼如果再增加一些要被調用的系統呢?比如:
這會讓付款系統變得非常複雜,每增加一個在付款成功之後需要調用的系統,就需要修改付款系統來進行相關的調用。優雅一點的實現是把這個付款成功後的服務調用變爲一種可擴展的配置,甚至可以動態生效,但這隻能降低變更時的開發和部署成本,並沒有降低複雜性。付款系統被迫要依賴非常多的系統。
引入消息中間件進行服務解耦
可以考慮一下,從付款的角度看,這些系統是付款系統必須依賴的嗎?答案是否定的,付款系統只需要驗證用戶賬號、付款賬號、付款密碼的合法性,所以付款系統依賴的是能夠系統用戶賬號、付款賬號、付款密碼的系統,而上圖中的系統其實都不是付款系統必須依賴的系統。相反,這些系統都是必須依賴付款系統的,因爲它們都關心付款是否成功。
在這樣的場景中,我們需要通過消息中間件把上面的結構解耦,上面結構中的服務調用將會被固定格式的消息傳遞所取代。付款系統負責向消息中間件發送消息,而其他的系統則向消息中間件來訂閱這個消息,然後完成自己的工作,如圖所示:
這樣,通過消息中間件,付款系統就不需要關心到底有多少個系統需要知道付款成功這件事情了,也不用關心如何通知它們,只需要把登陸成功這件事情轉化爲一個消息發送到消息中間件就好了,這樣,需要了解付款成功這件事情的系統自己去消息中間件訂閱就行了,並且各個系統之間也是互不影響的。
JMS概述
JMS是Java Message Service的縮寫,即Java消息服務,它是Java EE中一個關於消息的規範,而Hornetq、ActiveMQ等產品是對這個規範的實現。如果是企業內部或者一些小型的系統,直接使用JMS的實現產品是一個經濟的選擇,而在大型系統中有一些場景不適合使用JMS。
在大型互聯網中,我們採用消息中間件可以進行應用之間的解耦以及操作的異步,這是消息中間件兩個最基礎的特點,也正是我們所需要的。在此基礎上,我們着重思考的是消息的順序保證、擴展性、可靠性、業務操作與消息發送一致性,以及多集羣訂閱者等方面的問題。當然,這些我們要思考的東西,JMS都已經想到了,先看下JMS能幫開發者做什麼:
1、定義一組消息公用概念和實用工具
所有Java應用程序都可以使用JMS中定義的API去完成消息的創建、接收與發送,任何實現了JMS標準的MOM都可以作爲消息的中介,完成消息的存儲轉發
2、最大化消息應用程序的可移植性
MOM提供了有保證的消息發送,應用程序開發人員無需瞭解遠程過程調用(PRC)和網絡/通信協議的細節,提供了程序的可移植性
3、最大化降低應用程序與應用程序之間的耦合度
由於MOM的存在,各個應用程序只關心和MOM之間如何進行消息的接收與發送,而無須關注MOM的另一邊,其他程序是如何接收和發送的
JMS兩種消息模型
1、點對點模型
點對點模型(Pointer-to-Pointer)類似這樣:
這種模型總結幾點:
(1)一個消息中間件關聯多個隊列生產者和消費者
(2)一條消息僅僅能被一個消費者消費
(3)多個消費者正在監聽隊列上的消息,那麼中間件將根據先來先得的原則確定由哪個消費者接收下一條消息,如果沒有消費者正在監聽隊列,那麼消息將保留在中間件中,直至消費者連接到中間爲止
(4)收到消息後消費者必須確認消息已被接收,否則中間件江認爲該消息沒有被接收,那麼這條消息仍然可以被其他消費者接收。程序可以自動確認,不需要人工干預
(5)生產者和消費者的運行先後沒有限制
(6)此模型中,消息不是自動推送給消費者的,而是要消費者中間件中請求獲得
2、發佈/訂閱模型
發佈/訂閱(Publish-Subscribe)模型類似這樣:
這種模型中,還是以分點的形式總結:
(1)有一個重要的概念topic,可以認爲是主題
(2)生產者發佈消息,消費者訂閱感興趣的消息,生產者將消息和一個特定的topic(主題)連在一起,中間件將根據消費者註冊的topic,將消息傳遞給消費者
(3)發佈/訂閱模式允許多個消費者接收同一條消息,只要這些消費者註冊了同一個主題
(4)消費者必須先運行,訂閱主題,然後再等待生產者運行,這麼點對點模型有所差別
(5)該模型中,消息會自動廣播,消費者無須通過主動請求或者輪訓主題的方法來獲得新的消息
JMS爲提供的要素
JMS爲發開者提供了很多的要素,看一下比較重要的幾個:
要 素 | 作 用 |
Destination | 表示消息所走通道的目標定義,,用來定義消息從發送端發出後要走的通道,而不是接收方。Destination屬於管理類對象 |
ConnectionFactory | 顧名思義,用於創建連接對象,ConnectionFactory屬於管理類的對象 |
Connection | 連接接口,所負責的重要工作時創建Session |
Session | 會話接口,這是一個非常重要的對象,消息發送者、消息接收者以及消息對象本身,都是通過這個會話對象創建的 |
MessageConsumer | 消息的消費者,也就是訂閱消息並處理消息的對象 |
MessageProducer | 消息的生產者,也就是用來發送消息的對象 |
XXXMessage | 指各種類型的消息對象,包括ByteMesage、ObjectMessage、StreamMessage和TextMessage這5種 |
在JMS消息模型中,根據點對點模式和發佈/訂閱模式,這些要素由擴展出了各自的內容:
JMS標準 | 點對點模式 | 發佈/訂閱模式 |
ConnectionFactory | QueueConnectionFactory | TopicConnectionFactory |
Connection | QueueConnection | TopicConnection |
Destination | Queue | Topic |
Session | QueueSession | TopicSession |
MessageProducer | QueueSender | TopicPublisher |
MessageConsumer | QueueReceiver | TopicSubscriber |
JMS是一個標準,具體還是依賴實現,當前常見的JMS實現有ActiveMQ、ZeroMQ、RabbitMQ等,Kafka是一種類似JMS的實現,下一篇文章將會重點講解一下Kafka,至於爲什麼,還是和以前寫文章一樣的原因,因爲工作用,呵呵。