初識訊息中介軟體
維基百科上對於訊息中介軟體的定義是"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,至於為什麼,還是和以前寫文章一樣的原因,因為工作用,呵呵。