--- tags: 學習筆記 --- # Message Queue 概述 ===  ## 前言 MQ 訊息佇列。首先我們將簡單聊一下 MQ 的前世今生,再簡單介紹幾種常用訊息佇列協議 - MQTT - XMPP - Stomp - AMQPOpenWire 然後在這個基礎上介紹幾種 MQ 產品以及他們運作模式的差異比較。 ## 訊息處理 - **訊息**:資訊的載體 - **訊息協議**:按照一種統一的格式描述訊息,這種統一的格式稱之為訊息協議。 在所謂的軟體開發中很常會有一個情境是需要在不同的服務間傳遞、接收訊息, 這種訊息的傳遞接收,可以是 RPC、RestfulAPI、WebSocket、Kafka 等林林總總五花八門。 最主要可以區分為兩類: - 即時訊息通訊: - RPC - RestfulAPI - WebSocket - 延遲訊息通訊: - 訊息從某一端發出後,首先進入一個容器進行臨時儲存,當達到某種條件後,再由這個容器傳送給另一端。 這個容器的一種具體實現就是**訊息佇列**。 - ActiveMQ - RabbitMQ - Kafka ## 中介層(Middleware) ### 特點 - 中介層是軟體,而且是一大類具有不同功能的軟體,而不是一種具備某具體功能的軟體; - 中介層是伴隨著網路而應運而生的; - 中介層是應用軟體與系統軟體之間的「中介件」「介中軟體」,起到支撐與連接作用; - 中介層不是開發工具,但它具有開發、管理和部署的功能; - 中介層是為應用軟體服務的,應用軟體是為終端使用者服務的,終端使用者並不直接使用中介層; - 中介層不是大眾消費類軟體產品,除非是一個行業內的專業人士,普通消費者是不會接觸中介層的;在基礎軟體(作業系統、資料庫、中介層)中,中介層是最不為人所了解的; ### 作用 - 整合執行環境:中介軟體能夠封鎖、彌合底層執行環境中的差異性與異構性,確保整個系統在異構平台間能夠穩定執行; - 提高開發效率:中介軟體能夠提高開發效率,大幅縮短開發周期; - 軟體品質:中介軟體能夠明晰系統內的不同層級,對接不同的可插拔方式,從而保障軟體的品質; - 節約成本:中介軟體可大幅節省應用系統內的系統資源,並減少執行成本。 ### 訂單系統舉例 原始設計:  採用中介層:  ## MQ  ### 使用 MQ 的主要目的 - 解耦 解耦前  解耦後  - 異步處理 異步處理前  異步處理前  - 削峰填谷 削峰前  削峰後  ### MQ 分類 - 推模式(Push):由 MQ 主體**主動**將訊息推給消費者 - 訊息的傳遞掌控在產出並發送的端口(生產者) - 相對及時 - 主體無法確定此一訊息是否確實推送成功 - 無法確定消費者的負載 - 拉模式(Pull):由消費者自主向主體拉取訊息 - 消費者可針對自己當前負載狀況決定是否取得訊息(削峰填谷) - 未必能夠及時處理訊息 - 訊息可能堆積在主體 - 以拉模式為主,兼有推模式 ### 協議  從上圖可以看到,某一種訊息通訊軟體(或者叫做程式庫)的實現都建立在"協議"基礎上:RMI 程式庫建立在 RMI 協議上(RMI 協議是 JAVA 規範協議的一部分) ,屬於一種"即時訊息通訊";RabbitMQ 和 Qpid 訊息通訊軟體的設計依據是 AMQP 協議,屬於一種"延遲訊息通訊"。 雖然訊息協議存在"私有協議"和"開放協議"之分(是否向行業開放訊息規範文件、是否允許某個組織更改協議),雖然某一個軟體(程式庫)不一定只支援一種協議(例如ActiveMQ實現了多種訊息協議),雖然某一種協議也不一定只有一種軟體(程式庫)實現(例如能夠支援webservice協議的程式庫就有Codehaus XFire、Apache CXF、Jboss RESTEasy等),但是這並不影響 **"某一種訊息通訊軟體(或者叫做程式庫)的實現都建立在"協議"基礎上"的概念,反而是這個基本概念加強了**。 ### 比較 | 對比方向 | 概要 | | -------- | ------------------------------------------------------------ | | 吞吐量 | 萬級:ActiveMQ、RabbitMQ(ActiveMQ 的性能最差)、十萬級甚至是百萬級:RocketMQ 和 Kafka。 | | 可用性 | 都可以實現高可用性。ActiveMQ 和 RabbitMQ 基于主從架構實現。RocketMQ 基於分散式架構、Kafka 也是分散式的,一個訊息多個副本,少數機器當機,並不會丟失訊息。 | | 時效性 | RabbitMQ 基於 erlang 開發,所以併發能力較強,性能較佳、延時很低達到微秒級。其他三个都是 ms 級。 | | 支援功能 | 除了 Kafka,其他產品的功能都較為完整,Kafka 功能較為簡單,主要支援簡單的 MQ 功能,在大數據領域的實時計算與 Log 採集被廣泛使用。 | | 訊息丟失 | ActiveMQ 和 RabbitMQ 丢失的可能性非常低,RocketMQ 和 Kafka 理論上不會丟失。 | ### 實做 MQ 架構最需要注意的問題 - 訊息的可靠投遞:確保訊息不會丟失 - 訊息落地 - 超時,重傳,確認 - 訊息冪等性:使用同樣的條件,一次請求和重複多次請求對系統資源的影響是一致的。 - 分散式系統設計中,設計必須考慮,底層重試時(並不一定是應用層發起的,有時候是TCP 層,有時候是鏈接池層,有時候是框架層,這些重試,並不是應用層能夠控制的),系統不會異常,數據不會不一致。 - 關鍵是訊息去重複 - 生產者產出的訊息到 MQ 裡重複時的辨識排除 - 消費者取得訊息時如何識別這條訊息是否已有被使用過 ## Kafka Kafka 是基於 ZooKeeper 協調的一個分散式訊息隊列系統,可以以極高的效率以及可用性確保訊息傳達。 具備以下優點: - 高吞吐量、低延遲:每秒可以處理數十萬條訊息,延遲最低只需要幾 ms 即可。 - 可擴充套件性:透過向 Zookeeper 註冊,各個叢集可隨時建立或拔除。 - 永續性、可靠性:訊息會被持久化到硬碟中,並且備份防止丟失。 - 容錯性:多節點故允許其中節點失敗 - 高併發:支援數千個端點同時讀寫 也因此分散式系統多數都會搭配 Kafka 來充作多台伺服器之間分配服務請求或是 Log 收集的工具。 ### 架構  Kafka 與 Zookeeper 由以下數個角色組成:  - Brokers(Kafka 伺服器):就是個伺服器,接收從 Producer 來的訊息,允許 Consumer 讀取訊息。 - Producers(生產者):可以產生出各種訊息 Push 到 Brokers 上。 - Consumers(消費者):從 Brokers 中將訊息 Pull 下來。 - 原則上一個訊息從 Producer 送出至 Brokers 後,系統中所有的 Consumer 都會 Pull 到該條訊息(併發處理)。 - Group:也可以由 Group 將訊息 Pull 下來,並由 Group 中的其中一個 Consumer 處理(不同 Group 負責不同事務,Group 中的 Consumer 負責同樣的工作,透過在 Group 中新增多台Consummer可以將工作量分流,並確保只有單一台Consummer工作)。 - Zookeeper:協調及控制 Brokers、Consumer、Group 之間的訊息傳遞。 在 Kafka 中訊息的定義如下: - Topic:訊息的分類,Producer 可以控制將訊息送至哪些 Topic,Consumer 也可以決定要訂閱哪些 Topic。 - Partition:每個 Topic 可以分成數個 Partition,為的是將 Topic 訊息分散送至不同 Broker,由不同 Consumer Group 吃下不同 Partition 的訊息,由此達成高吞吐量的目標。 如圖所示,同一 Topic 可能可以分成不同 Partition 其中儲存不同的訊息,Consumer Group 來 Pull 訊息時,這些 Partition 訊息則會依隊列分配出去。 故一般而言我們可透過控制 Partition 及 Group 中 Consumer 的數量來進行負載平衡,值得注意的是若 Partition 高於 Consumer 數則可能會有 Consumer 需要處理一個以上 Partition 的訊息,而 Consumer 數若高於 Partition 則代表有 Consumer 會永遠接收不到訊息。  ### 採用 Kafka 應該如何確保訊息不丟失 - Producers 丟失 - Producer 在送訊息時一般是異步模式,可以改為採用同步模式傳送。(不推薦) - 維持異步生產訊息,但設定 callback function 再取得上次傳送結果後判斷是否重送。 - Kafka 內建自動重送設定(Producer 的 retries) - Consumers 丟失 - Consumer 從 partitions 消費訊息時,會自動設定一個 offset(偏移量)在該 partition,表示佇列中訊息已經消費到此。 - 可以改為不要自動提交 offset,改為手動,由 Consumer 確定處理完畢後才送交 offset(只要沒人宣告處理完畢 offset 就無法前進),但帶來的問題是若 Consumer 實質處理完,但要提交 offset 時 shutdown,該筆訊息可能會被當作沒人處理,改由新接手的 Consumer 消費(訊息重複)。 ### 採用 Kafka 應該如何確保訊息冪等 - Consumer 已經消費卻沒成功提交 offset - Consumer 端的業務處理應自行注意訊息冪等。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up