1.揭開消息中間件RabbitMQ的神祕面紗

當你看到這篇博文的時候,相信你至少已經知道RabbitMQ 是一個很是優秀的消息中間件,它使用專門處理高併發的Erlang 語言編寫而成的消息中間件產品。html

固然若是你不知道也不要緊,讀完本篇你將Get 如下技能:java

  • 爲何須要消息中間件?
  • 什麼是生產者?
  • 什麼是消費者?
  • 什麼是隊列?
  • 什麼是消息隊列?
  • 什麼是消息中間件?
  • 消息中間件有哪些?
  • 瞭解什麼時候使用RabbitMQ或Apache Kafka?
  • 什麼是RabbitMQ?

0x01 爲何須要消息中間件?

Web 應用都是基於 HTTP 協議的請求/響應模式,沒法像 TCP 協議那樣保持長鏈接,所以 Web 應用就很難像手機那樣實現實時的消息推送。node

就目前來看,Web 應用的消息推送方式主要有如下幾種:shell

1.Ajax 短輪詢

Ajax 輪詢主要經過頁面端的 JS 定時異步刷新任務來實現數據的加載,但這種方式實時效果較差,並且對服務端的壓力也較大。數據庫

2. 長輪詢

長輪詢主要也是經過 Ajax 機制,但區別於傳統的 Ajax 應用,長輪詢的服務器端會在沒有數據時阻塞請求直到有新的數據產生或者請求超時才返回,以後客戶端再從新創建鏈接獲取數據,具體實現方式見圖 1 所示。但長輪詢服務端會長時間地佔用資源,若是消息頻繁發送的話會給服務端帶來較大的壓力。apache

圖 1. 長輪詢實現方式編程

3.WebSocket 雙向通訊

WebSocket 是 HTML5 中一種新的通訊協議,可以實現瀏覽器與服務器之間全雙工通訊。若是瀏覽器和服務端都支持 WebSocket 協議的話,該方式實現的消息推送無疑是最高效、簡潔的。而且最新版本的 IE、Firefox、Chrome 等瀏覽器都已經支持 WebSocket 協議,Apache Tomcat 7.0.27 之後的版本也開始支持 WebSocket。瀏覽器

參考 基於 RabbitMQ 的實時消息推送安全

0x02  消息傳遞術語

2.1  什麼是生產者?

製做意味着發送。 一個發送消息的程序是一個生產者:服務器

Tips: P 表明生產者

2.2 什麼是消費者?

消費與接受有相似的意義。 消費者是一個主要等待接收消息的程序:

請注意,生產者,消費者和中間件沒必要駐留在同一主機上;

2.3 什麼是隊列?

  • 隊列是生活在RabbitMQ中的郵箱的名稱。 儘管消息流經RabbitMQ和您的應用程序,但它們只能存儲在隊列中。
  • 一個隊列只受主機內存和磁盤限制的約束,它本質上是一個很大的消息緩衝區。
  • 許多生產者能夠發送進入一個隊列的消息,而且許多消費者能夠嘗試從一個隊列接收數據。 這就是咱們表明隊列的方式:

 

2.4 什麼是消息隊列?

消息隊列(Message Queue)是一種應用間的通訊方式,消息發送後能夠當即返回,由消息系統來確保消息的可靠傳遞。

消息發佈者只管把消息發佈到 MQ 中而不用管誰來取,消息使用者只管從 MQ中取消息而無論是誰發佈的。這樣發佈者和使用者都不用知道對方的存在。

2.5 什麼是消息中間件?

消息隊列中間件(簡稱消息中間件)是指利用高效可靠的消息傳遞機制進行與平臺無關的數據交流,並基於數據通訊來進行分佈式系統的集成。

經過提供消息傳遞和消息排隊模型,它能夠在分佈式環境下提供應用解耦、彈性伸縮、冗餘存儲、流量削峯、異步通訊、數據同步等等功能,

其做爲分佈式系統架構中的一個重要組件,有着舉足輕重的地位.

傳統的信息系統做法多是收到一條消息就立刻同步存入數據庫,這種做法在小併發量的狀況下能夠很好的工做,但互聯網大併發環境下就是災難.

更多解釋請參考:消息隊列之 RabbitMQ

2.6 其餘概念

概念:

  • Brocker:消息隊列服務器實體。
  • Exchange:消息交換機,指定消息按什麼規則,路由到哪一個隊列。
  • Queue:消息隊列,每一個消息都會被投入到一個或者多個隊列裏。
  • Binding:綁定,它的做用是把exchange和queue按照路由規則binding起來。
  • Routing Key:路由關鍵字,exchange根據這個關鍵字進行消息投遞。
  • Vhost:虛擬主機,一個broker裏能夠開設多個vhost,用做不用用戶的權限分離。
  • Producer:消息生產者,就是投遞消息的程序。
  • Consumer:消息消費者,就是接受消息的程序。
  • Channel:消息通道,在客戶端的每一個鏈接裏,可創建多個channel,每一個channel表明一個會話任務。

消息隊列的使用過程大概以下:

  • 消息接收
    • 客戶端鏈接到消息隊列服務器,打開一個channel。
    • 客戶端聲明一個exchange,並設置相關屬性。
    • 客戶端聲明一個queue,並設置相關屬性。
    • 客戶端使用routing key,在exchange和queue之間創建好綁定關係。
  • 消息發佈
    • 客戶端投遞消息到exchange。
    • exchange接收到消息後,就根據消息的key和已經設置的binding,進行消息路由,將消息投遞到一個或多個隊列裏。
  • AMQP 裏主要要說兩個組件:
    • Exchange 和 Queue
    • 綠色的 X 就是 Exchange ,紅色的是 Queue ,這二者都在 Server 端,又稱做 Broker
    • 這部分是 RabbitMQ 實現的,而藍色的則是客戶端,一般有 Producer 和 Consumer 兩種類型。
    Exchange一般分爲四種:
    • fanout:該類型路由規則很是簡單,會把全部發送到該Exchange的消息路由到全部與它綁定的Queue中,至關於廣播功能
    • direct:該類型路由規則會將消息路由到binding key與routing key徹底匹配的Queue中
    • topic:與direct類型類似,只是規則沒有那麼嚴格,能夠模糊匹配和多條件匹配
    • headers:該類型不依賴於routing key與binding key的匹配規則來路由消息,而是根據發送的消息內容中的headers屬性進行匹配

0x03 消息中間件有哪些?

ActiveMQ 是 Apache 出品的、採用 Java 語言編寫的徹底基於 JMS1.1 規範的面向消息的中間件,爲應用程序提供高效的、可擴展的、穩定的和安全的企業級消息通訊。不過因爲歷史緣由包袱過重,目前市場份額沒有後面三種消息中間件多,其最新架構被命名爲 Apollo,號稱下一代 ActiveMQ,有興趣的同窗可行了解。

RabbitMQ 是採用 Erlang 語言實現的 AMQP 協議的消息中間件,最初起源於金融系統,用於在分佈式系統中存儲轉發消息。RabbitMQ 發展到今天,被愈來愈多的人承認,這和它在可靠性、可用性、擴展性、功能豐富等方面的卓越表現是分不開的。

Kafka 起初是由 LinkedIn 公司採用 Scala 語言開發的一個分佈式、多分區、多副本且基於 zookeeper 協調的分佈式消息系統,現已捐獻給 Apache 基金會。它是一種高吞吐量的分佈式發佈訂閱消息系統,以可水平擴展和高吞吐率而被普遍使用。目前愈來愈多的開源分佈式處理系統如 Cloudera、Apache Storm、Spark、Flink 等都支持與 Kafka 集成。

RocketMQ 是阿里開源的消息中間件,目前已經捐獻個 Apache 基金會,它是由 Java 語言開發的,具有高吞吐量、高可用性、適合大規模分佈式系統應用等特色,經歷過雙 11 的洗禮,實力不容小覷。

ZeroMQ 號稱史上最快的消息隊列,基於 C 語言開發。ZeroMQ 是一個消息處理隊列庫,可在多線程、多內核和主機之間彈性伸縮,雖然大多數時候咱們習慣將其納入消息隊列家族之中,可是其和前面的幾款有着本質的區別,ZeroMQ 自己就不是一個消息隊列服務器,更像是一組底層網絡通信庫,對原有的 Socket API 上加上一層封裝而已。

目前市面上的消息中間件還有不少,好比騰訊系的 PhxQueue、CMQ、Kafka 等,甚至NoSQL Redis聽說 也有消息 隊列的功能。

參考博文:IM系統的MQ消息中間件選型:Kafka仍是RabbitMQ?

0x04 瞭解什麼時候使用RabbitMQ或Apache Kafka?

英文原文:Understanding When to use RabbitMQ or Apache Kafka

人們作出選擇,情緒和我的喜愛每每是很是重要的因素,可是做爲一個有經驗的技術專家來講,確定是不能由於我的喜愛去草率作出決定的。

現在市場上有數十種消息傳遞技術,什麼樣的場景用什麼技術,這是一個技術專家應該考慮的問題。

現在最流行的選擇有兩種:RabbitMQ和Apache Kafka

因此接下來咱們將從起源,設計意圖,成功的案例,集成的功能和開發人員的體驗來對比回答什麼時候使用RabbitMQ或Apache Kafka問題。

4.1 起源

RabbitMQ 是一個「傳統」消息代理,能夠實現各類消息傳遞協議。它是首批實現合理級別功能,客戶端庫,開發工具和質量文檔的開源消息代理之一。RabbitMQ最初是爲實現AMQP而開發的,AMQP是一種開放式線路協議,具備強大的路由功能。雖然Java具備像JMS這樣的消息傳遞標準,但它對於須要分佈式消息傳遞的非Java應用程序沒有幫助,由於它嚴重限制了任何集成場景,微服務或單片機。隨着AMQP的出現,跨語言的靈活性成爲開源消息代理的真實存在。

Apache Kafka 是在Scala中開發的,最初是在LinkedIn(領英)上做爲鏈接不一樣內部系統的一種方式。當時,LinkedIn正在轉向更加分散的架構,須要從新構想數據集成和實時流處理等功能,從而擺脫之前單一的方法來解決這些問題。今天,Kafka在Apache Software Foundation產品生態系統中獲得了很好的採用,在事件驅動的架構中特別有用。 

4.2 架構設計

RabbitMQ

  • RabbitMQ被設計爲通用消息代理,採用點對點,request(請求)//reply(回覆)和pub-sub通訊樣式模式的多種變體。
  • 它使用智能 broker(代理)/dumb(啞) 消費者模型,專一於向消費者提供一致的消息傳遞,消費者的消費速度與經紀人跟蹤消費者狀態的速度大體類似。
  • 它是成熟的,在正確配置時表現良好,獲得很好的支持(客戶端庫Java,.NET,node.js,Ruby,PHP和更多語言),而且有許多可用的插件能夠將它擴展到更多的用例和集成場景。

簡化總體RabbitMQ架構   資料來源:http://kth.diva-portal.org/smash/get/diva2:813137/FULLTEXT01.pdf

RabbitMQ中的通訊能夠根據須要同步或異步。發佈者向交換髮送消息,消費者從隊列中檢索消息。經過交換將生產者與隊列分離可確保生產者不會受到硬編碼路由決策的影響。RabbitMQ還提供了許多分佈式部署方案(而且確實要求全部節點都可以解析主機名)。能夠將多節點羣集設置爲羣集聯合,而且不依賴於外部服務(但某些羣集造成插件可使用AWS API,DNS,Consul等)。  

Apache KafKa

Apache Kafka專爲高容量發佈 - 訂閱消息和流而設計,旨在持久,快速和可擴展。

從本質上講,Kafka提供了一個持久的消息存儲,相似於日誌,在服務器集羣中運行,它存儲稱爲主題的類別中的記錄流。

Figure 2 - Global Apache Kafka architecture (with 1 topic, 1 partition, replication factor 4). 資料來源:http://kth.diva-portal.org/smash/get/diva2:813137/FULLTEXT01.pdf 

 

 

每條消息都包含一個鍵,一個值和一個時間戳。幾乎與RabbitMQ相反,Kafka僱用了一個笨重的經紀人,並使用聰明的消費者來讀取它的緩衝區。Kafka不會嘗試跟蹤每一個消費者讀取的消息,只保留未讀消息; 相反,Kafka會在一段時間內保留全部消息,消費者有責任在每一個日誌(消費者狀態)中跟蹤他們的位置。所以,經過合適的開發人員建立消費者代碼,Kafka能夠支持大量消費者並以極少的開銷保留大量數據。如上圖所示,Kafka確實須要運行外部服務 - 在這種狀況下是Apache Zookeeper,這一般被認爲是很是容易理解,設置和操做的。

Requirements and Use Cases 要求和用例

Apache Kafka

許多開發人員在乎識到必須將大量內容鏈接在一塊兒時開始探索消息傳遞,而其餘集成模式(如共享數據庫)則不可行或太危險。

Apache Kafka包括代理自己,它其實是最着名和最受歡迎的部分,而且已經設計並突出地推向流處理場景。除此以外,Apache Kafka最近還添加了Kafka Streams,它將本身定位爲Apache Spark,Apache Flink,Apache Beam / Google Cloud Data Flow和Spring Cloud Data Flow等流媒體平臺的替代品。該文檔很好地討論了網站活動跟蹤,度量標準,日誌聚合,流處理,事件採購和提交日誌等常見用例它描述的其中一個用例是消息傳遞,它可能會產生一些混亂。所以,讓咱們解決一下,並清楚瞭解哪些消息傳遞方案最適合Kafka,例如:

  • 從A到B流,沒有複雜的路由,最大吞吐量(100k / sec +),按分區順序至少提交一次。
  • 當您的應用程序須要訪問流歷史記錄時,至少按分區順序提供一次。Kafka是一個持久的消息存儲,客戶能夠根據須要「重播」事件流,而不是更傳統的消息代理,一旦消息傳遞,它就會從隊列中刪除。
  • 流處理
  • 活動採購

RabbitMQ

RabbitMQ是一種通用消息傳遞解決方案,一般用於容許Web服務器快速響應請求,而不是在用戶等待結果時強制執行資源繁重的過程。它還能夠將消息分發給多個接收者以供消費,或者在高負載(20k + / sec)下平衡負載之間的負載。當您的需求超出吞吐量時,RabbitMQ可提供許多功能可靠的交付,路由,聯合,HA,安全性,管理工具和其餘功能讓咱們來看看RabbitMQ的最佳場景,例如:

  • 您的應用程序須要使用現有協議的任意組合,如AMQP 0-9-1,STOMP,MQTT,AMQP 1.0。
  • 您須要基於每一個消息(死信隊列等)進行更精細的一致性控制/保證。可是,Kafka最近添加了更好的事務支持。 
  • 您的應用程序須要點對點,請求/回覆以及發佈/訂閱消息傳遞的多樣性
  • 複雜的路由到消費者,使用非平凡的路由邏輯集成多個服務/應用程序

RabbitMQ還能夠有效地解決上面幾個Kafka強大的用例,可是在其餘軟件的幫助下。當應用程序須要訪問流歷史時,RabbitMQ一般與Apache Cassandra一塊兒使用,對於須要「無限」隊列的應用程序,RabbitMQ一般與LevelDB插件一塊兒使用,但這兩種功能都不附帶RabbitMQ自己。

爲了更深刻地瞭解Kafka和RabbitMQ的微服務特定用例,請訪問Pivotal博客並閱讀Fred Melo的這篇簡短帖子

開發經驗

RabbitMQ

RabbitMQ正式支持Java,Spring,.NET,PHP,Python,Ruby,JavaScript,Go,Elixir,Objective-C,Swift - 經過社區插件與許多其餘客戶端和devtools一塊兒支持。RabbitMQ客戶端庫已經成熟而且文檔齊全

Apache Kafaka

Apache Kafka在這方面取得了長足進步,雖然它只提供了一個Java客戶端,可是社區開源客戶端,生態系統項目以及適配器SDK的目錄不斷增長,能夠構建本身的系統集成大部分配置是經過.properties文件或以編程方式完成的。

這兩個選項的普及對許多其餘軟件提供商產生了很大的影響,這些軟件提供商確保RabbitMQ和Kafka在他們的技術上運行良好。

至於開發人員的體驗...值得一提的是咱們在Spring KafkaSpring Cloud Stream等中提供的支持。 

安全和運營

RabbitMQ

二者都是RabbitMQ的優點。RabbitMQ管理插件提供HTTP API,基於瀏覽器的管理和監控UI,以及運營商的CLI工具。長期監控數據存儲須要使用CollectD,Datadog或New Relic等外部工具。RabbitMQ還提供用於監控,審計和應用程序故障排除的API和工具。除了支持TLS以外,RabbitMQ還附帶了由內置數據存儲,LDAP或基於HTTPS的外部提供程序支持的RBAC,並支持使用x509證書而不是用戶名/密碼對進行身份驗證。使用插件能夠至關簡單地開發其餘身份驗證方法。

Kafaka

這些領域對Apache Kafka構成了挑戰。在安全方面,最近的Kafka 0.9版本添加了TLS,基於JAAS角色的訪問控制和kerberos / plain / scram auth,使用CLI管理安全策略。這對早期版本進行了實質性改進,您只能鎖定網絡級別的訪問權限,這對於共享或多租戶來講效果不佳。

Kafka使用由shell腳本,屬性文件和特定格式的JSON文件組成的管理CLI。Kafka Brokers,生產商和消費者經過Yammer / JMX發佈指標,但沒有保留任何歷史記錄,這實際上意味着使用第三方監控系統。使用這些工具,操做能夠管理分區和主題,檢查消費者偏移位置,並使用Apache Zookeeper爲Kafka提供的HA和FT功能。雖然許多人認爲對Zookeeper的要求存在高度懷疑,但它確實爲Kafka用戶帶來了集羣優點。

例如,3節點Kafka集羣即便在2次故障後系統也能正常運行。可是,若是要在Zookeeper中支持儘量多的故障,則須要額外的5個Zookeeper節點,由於Zookeeper是基於仲裁的系統,而且只能容忍N / 2 + 1故障。這些顯然不該該與Kafka節點共存 - 因此要創建一個3節點的Kafka系統,你須要~8臺服務器。在推斷任何Kafka系統的可用性時,運營商必須考慮ZK集羣的屬性,不管是在資源消耗仍是設計方面。

性能

Kafka

Kafka在設計上大放異彩:100k / sec的性能一般是人們選擇Apache Kafka的關鍵驅動因素。  

固然,每秒消息的速率很難說明和量化,由於它們依賴於不少,包括你的環境和硬件,你的工做負載的性質,使用的交付保證(例如持久性成本高,鏡像甚至更多)等等。

RabbitMQ

每秒20K消息很容易經過單個Rabbit隊列推送,實際上並不比這更難,對保證方式的要求不高。該隊列由一個Erlang輕量級線程支持,該線程在本機操做系統線程池上進行協做調度 - 所以它成爲一個天然的瓶頸或瓶頸,由於單個隊列永遠不會作更多的工做,而不是讓CPU週期工做在。

每秒增長消息一般歸結爲經過巧妙的路由(例如,能夠同時運行不一樣的隊列)來執行諸如跨多個隊列中斷流量之類的事情來正確利用一個環境中可用的並行性。當RabbitMQ 每秒實現100萬條消息時,這個用例基本上徹底是爲了明智地作到這一點 - 可是使用了大量資源,大約30個RabbitMQ節點實現了。大多數RabbitMQ用戶都享有卓越的性能,集羣由3到7個RabbitMQ節點組成。

0x05 什麼是RabbitMQ?

RabbitMQ 官網:http://www.rabbitmq.com/

RabbitMQ是部署最普遍的開源消息代理。

RabbitMQ在全球範圍內在小型初創公司和大型企業進行了超過35,000次的生產部署,是最受歡迎的開源消息代理。

RabbitMQ輕巧且易於部署在雲端和雲端。 它支持多種消息傳遞協議。 RabbitMQ能夠部署在分佈式和聯合配置中,以知足高規模,高可用性需求。

RabbitMQ可運行在許多操做系統和雲環境中,併爲大多數流行語言提供普遍的開發工具。

————官網解釋

RabbitMQ是實現了高級消息隊列協議(AMQP)的開源消息代理軟件(亦稱面向消息的中間件)。

RabbitMQ服務器是用Erlang語言編寫的,而羣集和故障轉移是構建在開放電信平臺框架上的。

———— 維基百科

Tips: 

在最近研讀的Think in Java 第四版中有這樣一段話:

若是你發現程序中某個部分必須大量使用併發,而且你在試圖構建這個部分時碰到了過多的問題,那麼你能夠考慮使用Erlang 這類專門的併發語言來建立這個部分。

本篇完~

更多請看個人RabbitMQ 學習專欄:http://www.javashuo.com/article/p-qqwuyhfr-mq.html

相關文章
相關標籤/搜索