rocketmq總結(消息的高可用、中間件選型)

rocketmq總結(消息的高可用、中間件選型)java

 

 

 參考:linux

https://blog.csdn.net/meilong_whpu/article/details/76922456ios

http://blog.51cto.com/sofar/1540874git

https://blog.csdn.net/lunaqi/article/details/78517200程序員

https://mp.weixin.qq.com/s?__biz=MzIwMzg1ODcwMw==&mid=2247487688&idx=1&sn=d1555109750b309a2d96ce3332e8a97b&chksm=96c9a6a8a1be2fbe8e1df2f2bb60a2bfea0e62aaec0633df928432ceed6438a724dd217624cd#rd github

 

 

消息中間件概況

消息隊列技術是分佈式應用間交換信息的一種技術。消息隊列可駐留在內存或磁盤上,隊列存儲消息直到它們被應用程序讀走。經過消息隊列,應用程序可獨立地執行--它們不須要知道彼此的位置、或在繼續執行前不須要等待接收程序接收此消息。sql

       在分佈式計算環境中,爲了集成分佈式應用,開發者須要對異構網絡環境下的分佈式應用提供有效的通訊手段。爲了管理須要共享的信息,對應用提供公共的信息交換機制是重要的。數據庫

       設計分佈式應用的方法主要有:遠程過程調用(PRC)-分佈式計算環境(DCE)的基礎標準成分之一;對象事務監控(OTM)-基於CORBA的面向對象工業標準與事務處理(TP)監控技術的組合;消息隊列(MessageQueue)-構造分佈式應用的鬆耦合方法。編程

       (a) 分佈計算環境/遠程過程調用 (DCE/RPC)vim

       RPC是DCE的成分,是一個由開放軟件基金會(OSF)發佈的應用集成的軟件標準。RPC模仿一個程序用函數引用來引用另外一程序的傳統程序設計方法,此引用是過程調用的形式,一旦被調用,程序的控制則轉向被調用程序。

       在RPC 實現時,被調用過程可在本地或遠地的另外一系統中駐留並在執行。當被調用程序完成處理輸入數據,結果放在過程調用的返回變量中返回到調用程序。RPC完成後程序控制則當即返回到調用程序。所以RPC模仿子程序的調用/返回結構,它僅提供了Client(調用程序)和Server(被調用過程)間的同步數據交換。

       (b) 對象事務監控 (OTM)

       基於CORBA的面向對象工業標準與事務處理(TP)監控技術的組合,在CORBA規範中定義了:使用面向對象技術和方法的體系結構;公共的 Client/Server程序設計接口;多平臺間傳輸和翻譯數據的指導方針;開發分佈式應用接口的語言(IDL)等,併爲構造分佈的 Client/Server應用提供了普遍及一致的模式。

       (c) 消息隊列 (Message Queue)

       消息隊列爲構造以同步或異步方式實現的分佈式應用提供了鬆耦合方法。消息隊列的API調用被嵌入到新的或現存的應用中,經過消息發送到內存或基於磁盤的隊列或從它讀出而提供信息交換。消息隊列可用在應用中以執行多種功能,好比要求服務、交換信息或異步處理等。

       中間件是一種獨立的系統軟件或服務程序,分佈式應用系統藉助這種軟件在不一樣的技術之間共享資源,管理計算資源和網絡通信。它在計算機系統中是一個關鍵軟件,它能實現應用的互連和互操做性,能保證系統的安全、可靠、高效的運行。中間件位於用戶應用和操做系統及網絡軟件之間,它爲應用提供了公用的通訊手段,而且獨立於網絡和操做系統。中間件爲開發者提供了公用於全部環境的應用程序接口,當應用程序中嵌入其函數調用,它即可利用其運行的特定操做系統和網絡環境的功能,爲應用執行通訊功能。

       若是沒有消息中間件完成信息交換,應用開發者爲了傳輸數據,必需要學會如何用網絡和操做系統軟件的功能,編寫相應的應用程序來發送和接收信息,且交換信息沒有標準方法,每一個應用必須進行特定的編程從而和多平臺、不一樣環境下的一個或多個應用通訊。例如,爲了實現網絡上不一樣主機系統間的通訊,將要求具有在網絡上如何交換信息的知識(好比用TCP/IP的socket程序設計);爲了實現同一主機內不一樣進程之間的通信,將要求具有操做系統的消息隊列或命名管道(Pipes)等知識。

       目前中間件的種類不少,如交易管理中間件、面向Java應用的Web應用服務器中間件等,而消息傳輸中間件(MOM)是其中的一種。它簡化了應用之間數據的傳輸,屏蔽底層異構操做系統和網絡平臺,提供一致的通信標準和應用開發,確保分佈式計算網絡環境下可靠的、跨平臺的信息傳輸和數據交換。它基於消息隊列的存儲-轉發機制,並提供特有的異步傳輸機制,可以基於消息傳輸和異步事務處理實現應用整合與數據交換。

 

發佈-訂閱消息模式

1、 訂閱雜誌

      咱們不少人都訂過雜誌,其過程很簡單。只要告訴郵局咱們所要訂的雜誌名、投遞的地址,付了錢就OK。出版社按期會將出版的雜誌交給郵局,郵局會根據訂閱的列表,將雜誌送達消費者手中。這樣咱們就能夠看到每一期精彩的雜誌了。

 

仔細思考一下訂雜誌的過程,咱們會發現這樣幾個特色:一、 消費者訂雜誌不須要直接找出版社;二、 出版社只須要把雜誌交給郵局;三、 郵局將雜誌送達消費者。郵局在整個過程當中扮演了很是重要的中轉做用,在出版社和消費者相互不須要知道對方的狀況下,郵局完成了雜誌的投遞。
2、 發佈-訂閱消息模式

       剛剛講了訂閱雜誌,下面咱們會講傳統調用模式演化到發佈-訂閱消息模式。
       有些網站在註冊用戶成功後發一封激活郵件,用戶收到郵件後點擊激活連接後才能使用該網站。通常的作法是在註冊用戶業務邏輯中調用發送郵件的邏輯。這 樣用戶業務就依賴於郵件業務。若是之後改成短信激活,註冊用戶業務邏輯就必須修改成調用發送短信的邏輯。若是要註冊後給用戶加點積分,再加一段邏輯。通過 屢次修改,咱們發現很簡單的註冊用戶業務已經愈來愈複雜,愈來愈難以維護。相信不少開發者都會有相似痛苦的經歷。

即便用戶業務實現中對其餘業務是接口依賴,也避免不了業務變化帶來的依賴影響。怎麼辦?解耦!將註冊用戶業務邏輯中註冊成功後的處理剝離出來。
       再回頭看看"訂閱雜誌",若是沒有郵局,出版社就必須本身將雜誌送達全部消費者。這種情形就和如今的註冊用戶業務同樣。咱們發現問題了,在用戶業務和其餘業務之間缺乏了郵局所扮角色。
       咱們把郵局抽象成一個管理消息的地方,叫"消息管理器"。註冊用戶成功後發送一個消息給消息管理器,由消息管理器轉發該消息給須要處理的業務。如今,用戶業務只依賴於消息管理器了,它不再會爲了註冊用戶成功後的其餘處理而煩惱。

註冊用戶的改造就是借鑑了"訂閱雜誌"這樣原始的模式。咱們再進一步抽象,用戶業務就是消息的"生產者",它將消息發佈到消息管理器。郵件業務就是 消息的"消費者",它將收到的消息進行處理。郵局能夠訂閱不少種雜誌,雜誌都是經過某種編號來區分;消息管理器也能夠管理多種消息,每種消息都會有一個 "主題"來區分,消費者都是經過主題來訂閱的。

發佈-訂閱消息模式已經呈如今咱們面前,利用它能夠產生更靈活、更鬆散耦合的系統。

 

MQ相關概念

1.消息(Message)

消息是MQ中最小的概念,本質上就是一段數據,它能被一個或者多個應用程序所理解,是應用程序之間傳遞的信息載體。

2.隊列(Queue)

2.1本地隊列

本地隊列按照功能可劃分爲初始化隊列,傳輸隊列,目標隊列和死信隊列。

初始化隊列用做消息觸發功能。

傳輸隊列只是暫存待傳的消息,條件許可的狀況下,經過管道將消息傳送到其餘的隊列管理器。

目標隊列是消息的目的地,能夠長期存放消息。

若是消息不能送達目標隊列,也不能再路由出去,則被自動放入死信隊列保存。

2.2別名隊列&遠程隊列

只是一個隊列定義,用來指定遠端隊列管理器的隊列。使用了遠程隊列,程序就不須要知道目標隊列的位置。

2.3模型隊列

模型隊列定義了一套本地隊列的屬性結合,一旦打開模型隊列,隊列管理器會按照這些屬性動態地建立出一個本地隊列。

3.隊列管理器(Queue Manager)

隊列管理器是一個負責嚮應用程序提供消息服務的機構,若是把隊列管理器比做數據庫,那麼隊列就是其中一張表。

4.通道(Channel)

通道是兩個管理器之間的一種單向點對點的的通訊鏈接,若是須要雙向交流,能夠創建一對通道。

5.監聽器(listner)

MQ產品的特性

可靠性傳輸

這個特色能夠說是消息中間件的立足之本,對於應用來講,只要成功把數據提交給消息中間件,那麼關於數據可靠傳輸的問題就由消息中間件來負責。

不重複傳輸

不重複傳播也就是斷點續傳的功能,特別適合網絡不穩定的環境,節約網絡資源。

異步性傳輸

異步性傳輸是指,接受信息雙方沒必要同時在線,具備脫機能力和安全性。

消息驅動

接到消息後主動通知消息接收方。

支持事務

應用程序能夠把一些數據更新組合成一個工做單元,這些更新一般是邏輯相關的,爲了保障數據完整性,全部的更新必須同時成功或者同時失敗)。 

MQ適用場景介紹

MQ消息隊列是應運鬆偶合的概念而產生的,主要以隊列和發佈訂閱爲消息傳輸機制,以異步的方式將消息可靠的傳輸到消費端的一種基礎產品。

它被普遍的應用與跨平臺、跨系統的分佈式系統之間,爲它們提供高效可靠的異步傳輸機制。

  • 消息通道(Message Channel)

       使用MQ將彼此協做的客戶端和服務端鏈接起來,使他們能夠交換消息。

如客戶端與服務端須要安全可靠的交互,能夠將一個MQ的隊列做爲安全通道,是客戶端與服務端可以安全高效的進行異步通信。

  • 消息總線(Message Bus)

      對於由許多獨立開發的服務組成的分佈式系統,假若要將它們組成一個完整的系統,這些服務必須可以可靠地交互,同時,爲了系統的健壯性,

每一個服務之間又不能產生過度緊密的依賴關係,這樣就能夠經過消息總線將不一樣的服務鏈接起來,容許它們異步的傳遞數據。

 

  • 消息路由(Message Router)

       經過消息路由,能夠將發送到MQ指定隊列的消息根據規則路由到不一樣的隊列。

此外,JMS規範還支持經過selector條件,對消息進行過濾,能夠用多個消費者消費同一個隊列的消息,每一個消費者只消費本身感興趣的消息。

  • 發佈/訂閱(Publicsher/Subscriber)

      發佈/訂閱模式用於一對多的通信,當消息發佈者向一個主題(Topic)發送一條消息後,該主題的全部訂閱者都會收到這條消息。

 

 

 

 

RocketMQ存儲篇—高可用

在集羣模式的部署方式中,Master與Slave配對是經過指定相同的brokerName參數來配對,Master的BrokerId必須是0,Slave的BrokerId必須是大於0的數。一個Master下面能夠掛載多個Slave,同一個Master下的多個Slave經過指定不一樣的BrokerId來區分。有4種部署方式:

部署方式 優勢 缺點 備註
單個Master模式 一旦Broker重啓或者宕機時,會致使整個服務不可用,不建議線上環境使用;    
多個Master模式 配置簡單,單個Master宕機或重啓維護對應用無影響,在磁盤配置爲RAID10時,即便機器宕機不可恢復狀況下,因爲RAID10磁盤很是可靠,消息也不會丟(異步刷盤丟失少許消息,同步刷盤一條不丟),性能最高。 單臺機器宕機期間,這臺機器上未被消費的消息在機器恢復以前不可訂閱,消息實時性會收到影響。 當使用多master無slave的集羣搭建方式時,master的brokerRole配置必須爲ASYNC_MASTER。若是配置爲SYNC_MASTER,則producer發送消息時,返回值的SendStatus會一直是SLAVE_NOT_AVAILABLE。
多Master多Slave模式——異步複製 即便磁盤損壞,消息丟失的很是少,但消息實時性不會受影響,由於Master宕機後,消費者仍然能夠從Slave消費,此過程對應用透明,不須要人工干預,性能同多Master模式幾乎同樣。 Master宕機,磁盤損壞狀況,會丟失少許信息。  
多Master多Slave模式——同步雙寫 數據與服務都無單點,Master宕機狀況下,消息無延遲,服務可用性與數據可用性都很是高; 性能比異步複製模式稍低,大約低10%左右,發送單個消息的RT會稍高,目前主宕機後,備機不能自動切換爲主機,後續會支持自動切換功能。  

在集羣模式下,爲了保證高可用,必需要保證備用Broker與主用Broker信息是一致的,在備用Broker初始化時設置的了定時任務,每一個60秒調用SlaveSynchronize.syncAll()方法發起向主用Broker進行一次config類文件的同步,而消息數據的同步由主備Broker經過心跳檢測的方式完成,每隔5秒進行一次心跳。 主用Broker提供讀寫服務,而備用Broker只提供讀服務。

 

刷盤方式

同步刷盤:在消息到達MQ後,RocketMQ須要將數據持久化,同步刷盤是指數據到達內存以後,必須刷到commitlog日誌以後纔算成功,而後返回producer數據已經發送成功。

異步刷盤:是指數據到達內存以後,返回producer說數據已經發送成功。,而後再寫入commitlog日誌。

commitlog:

commitlog就是來存儲全部的元信息,包含消息體,相似於Mysql、Oracle的redolog,因此主要有CommitLog在,Consume Queue即便數據丟失,仍然能夠恢復出來。

consumequeue:記錄數據的位置,以便Consume快速經過consumequeue找到commitlog中的數據

 

分佈式消息隊列RocketMQ部署與監控

==========================================================================================

1、RocketMQ簡介

==========================================================================================

RocketMQ是一款分佈式、隊列模型的消息中間件,具備如下特色:

一、支持嚴格的消息順序;

二、支持Topic與Queue兩種模式;

三、億級消息堆積能力;

四、比較友好的分佈式特性;

五、同時支持Push與Pull方式消費消息;

 

更多介紹能夠參考如下連接:

https://github.com/alibaba/RocketMQ/wiki

http://blog.csdn.net/a19881029/article/details/34446629

http://singlefly.blog.51cto.com/4658189/1368579

 

本文采用雙Master的架構模式。

 

==========================================================================================

2、服務器分佈

==========================================================================================

1、相關說明

IP地址

主機名

機型

角色

架構模式

10.217.121.123

rocketmq-master1

128G內存

nameserver、brokerserver

Master1(雙Master模式)

10.217.122.31

rocketmq-master2

128G內存

nameserver、brokerserver

Master2(雙Master模式)

 

2hosts信息添加

# vim /etc/hosts

10.217.121.123  mqnameserver1

10.217.122.31    mqnameserver2

10.217.121.123  rocketmq-master1

10.217.122.31    rocketmq-master2

 

3、系統環境

CentOS 6.3

 

4、整體架構

wKioL1PuQE3DcTjUAAE4E08WEfw644.jpg

 

==========================================================================================

3、RocketMQ安裝與配置

==========================================================================================

1JDK安裝

http://download.oracle.com/otn-pub/java/jdk/7u65-b17/jdk-7u65-linux-x64.tar.gz

# tar xvzf jdk-7u65-linux-x64.gz -C /usr/local

# rm -f jdk-7u65-linux-x64.gz

# cd /usr/local && ln -s jdk1.7.0_65 jdk

# cd /usr/local/bin && ln -s /usr/local/jdk/bin/java

 

2RocketMQ安裝

https://github.com/alibaba/RocketMQ/releases

# tar xvzf alibaba-rocketmq-3.1.7.tar.gz -C /usr/local

# mv alibaba-rocketmq alibaba-rocketmq-3.1.7

# ln -s alibaba-rocketmq-3.1.7 rocketmq

# rm alibaba-rocketmq-3.1.7.tar.gz

# ll /usr/local

wKiom1PuP2TDorXeAAKWNuNdZ7w687.jpg

 

3、環境變量設置

# vim /etc/profile

export PATH=$PATH:/usr/local/bin

 

export JAVA_HOME=/usr/local/jdk

export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

export PATH=$PATH:$JAVA_HOME/bin

 

export ROCKETMQ_HOME=/usr/local/rocketmq

export PATH=$PATH::$ROCKETMQ_HOME/bin

 

# source /etc/profile

# cd /usr/local/rocketmq/bin && sh os.sh

 

4、主機名設置

(1)Master1服務器

# vim /etc/hosts

10.217.121.123  mqnameserver1

10.217.122.31    mqnameserver2

10.217.121.123  rocketmq-master1

10.217.122.31    rocketmq-master2

 

# sed -i  '/HOSTNAME/d' /etc/sysconfig/network

# echo 'HOSTNAME=rocketmq-master1'  >> /etc/sysconfig/network

# hostname rocketmq-master1

 

(2)Master2服務器

# vim /etc/hosts

10.217.121.123  mqnameserver1

10.217.122.31    mqnameserver2

10.217.121.123  rocketmq-master1

10.217.122.31    rocketmq-master2

 

# sed -i  '/HOSTNAME/d' /etc/sysconfig/network

# echo 'HOSTNAME=rocketmq-master2'  >> /etc/sysconfig/network

# hostname rocketmq-master2

 

5RocketMQ配置

(1)Master1服務器

# vim /usr/local/rocketmq/conf/2m-noslave/broker-a.properties

brokerClusterName=AdpMqCluster

brokerName=broker-a

brokerId=0

namesrvAddr=mqnameserver1:9876;mqnameserver2:9876

defaultTopicQueueNums=4

autoCreateTopicEnable=true

autoCreateSubscriptionGroup=true

listenPort=10911

deleteWhen=04

fileReservedTime=120

mapedFileSizeCommitLog=1073741824

mapedFileSizeConsumeQueue=50000000

destroyMapedFileIntervalForcibly=120000

redeleteHangedFileInterval=120000

diskMaxUsedSpaceRatio=88

 

storePathRootDir=/data/rocketmq/store

storePathCommitLog=/data/rocketmq/store/commitlog

 

maxMessageSize=65536

 

flushCommitLogLeastPages=4

flushConsumeQueueLeastPages=2

flushCommitLogThoroughInterval=10000

flushConsumeQueueThoroughInterval=60000

 

brokerRole=ASYNC_MASTER

flushDiskType=ASYNC_FLUSH

 

checkTransactionMessageEnable=false

 

sendMessageThreadPoolNums=128

pullMessageThreadPoolNums=128

 

(2)Master2服務器

# vim /usr/local/rocketmq/conf/2m-noslave/broker-b.properties

brokerClusterName=AdpMqCluster

brokerName=broker-b

brokerId=1

namesrvAddr=mqnameserver1:9876;mqnameserver2:9876

defaultTopicQueueNums=4

autoCreateTopicEnable=true

autoCreateSubscriptionGroup=true

listenPort=10911

deleteWhen=04

fileReservedTime=120

mapedFileSizeCommitLog=1073741824

mapedFileSizeConsumeQueue=50000000

destroyMapedFileIntervalForcibly=120000

redeleteHangedFileInterval=120000

diskMaxUsedSpaceRatio=88

 

storePathRootDir=/data/rocketmq/store

storePathCommitLog=/data/rocketmq/store/commitlog

 

maxMessageSize=65536

 

flushCommitLogLeastPages=4

flushConsumeQueueLeastPages=2

flushCommitLogThoroughInterval=10000

flushConsumeQueueThoroughInterval=60000

 

brokerRole=ASYNC_MASTER

flushDiskType=ASYNC_FLUSH

 

checkTransactionMessageEnable=false

 

sendMessageThreadPoolNums=128

pullMessageThreadPoolNums=128

 

(3)runbroker.sh參數調整

runbroker.sh須要根據內存大小進行適當地調整

JAVA_OPT_1="-server-Xms80g -Xmx80g -Xmn20g -XX:PermSize=1g -XX:MaxPermSize=1g"

 

6、服務啓動

# mkdir -p /data/rocketmq/store/commitlog  /data/logs

# cd /usr/local/rocketmq/conf && sed -i  's#${user.home}#/data#g' *.xml

 

(1)、啓動NameServermaster1master2

# cd /usr/local/rocketmq/bin

# nohup sh mqnamesrv &

 

(2)、啓動BrokerServer Amaster1

# cd /usr/local/rocketmq/bin

# nohup sh mqbroker -c ../conf/2m-noslave/broker-a.properties  >/dev/null 2>&1 &

 

(3)、啓動BrokerServer Bmaster2

# cd /usr/local/rocketmq/bin

# nohup sh mqbroker -c ../conf/2m-noslave/broker-b.properties  >/dev/null 2>&1 &

 

# netstat -ntlp

wKioL1PuQKejDpe9AAC166EAySE757.jpg

 

# jps

wKiom1PuP6yBTpSfAAB_ScYujDc698.jpg

 

==========================================================================================

4、RocketMQ服務健康監控

==========================================================================================

1、依賴組件安裝

# yum -y install nmap

 

2nameserver監控

# vim /data/scripts/check_nameserver_health.sh

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
 
SRV_PORT="9876"                    ## 端口號
SRV_PROT="tcp"                     ## 協議類型
SRV_NAME="rocketmq_nameserver"     ## 服務名
 
## 是否已正確掃描
SCAN_FLAG=0
 
for ETH_NAME in `/sbin/ifconfig | grep eth1 | awk '{print $1}'`
do
       ETH1_ADDR=`/sbin/ifconfig ${ETH_NAME} | awk -F ':' '/inet addr/{print $2}' | sed 's/[a-zA-Z ]//g'`
       [[ -z "${ETH1_ADDR}" ]] && continue || break
done
 
TMP_SRV_PROT=`echo ${SRV_PROT} | tr '[A-Z]' '[a-z]'`
 
if [[ "${TMP_SRV_PROT}" == "tcp" ]]; then
       PROT_OPT="S"
elif [[ "${TMP_SRV_PROT}" == "udp" ]]; then
       PROT_OPT="U"
else
       echo "未知的協議類型!" && exit1
fi
 
## 最多掃描3次,成功一次便可,以免網絡抖動而致使誤判
for ((i=0; i<3; i++)); do
       RETVAL=`/usr/bin/nmap -n -s${PROT_OPT} -p ${SRV_PORT} ${ETH1_ADDR} | grep open`
       [[ -n "${RETVAL}" ]] && SCAN_FLAG=1;break || sleep 10
done
 
if [[ ${SCAN_FLAG} -ne 1 ]]; then
       [[ -n `ps aux | grep java | grep namesrv` ]] && kill -9 `ps aux | grep java | awk '/namesrv/{print $2}'`
       cd /usr/local/rocketmq/bin && nohup sh mqnamesrv &
fi

 

3brokerserver監控

# vim /data/scripts/check_brokerserver_health.sh

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
 
SRV_PORT="10911"                      ## 端口號
SRV_PROT="tcp"                        ## 協議類型
SRV_NAME="rocketmq_brokerserver"      ## 服務名
 
## 是否已正確掃描
SCAN_FLAG=0
 
for ETH_NAME in `/sbin/ifconfig | grep eth1 | awk '{print $1}'`
do
       ETH1_ADDR=`/sbin/ifconfig ${ETH_NAME} | awk -F ':' '/inet addr/{print $2}' | sed 's/[a-zA-Z ]//g'`
       [[ -z "${ETH1_ADDR}" ]] && continue || break
done
 
TMP_SRV_PROT=`echo ${SRV_PROT} | tr '[A-Z]' '[a-z]'`
 
if [[ "${TMP_SRV_PROT}" == "tcp" ]]; then
       PROT_OPT="S"
elif [[ "${TMP_SRV_PROT}" == "udp" ]]; then
       PROT_OPT="U"
else
       echo "未知的協議類型!" && exit1
fi
 
## 最多掃描3次,成功一次便可,以免網絡抖動而致使誤判
for ((i=0; i<3; i++)); do
       RETVAL=`/usr/bin/nmap -n -s${PROT_OPT} -p ${SRV_PORT} ${ETH1_ADDR} | grep open`
       [[ -n "${RETVAL}" ]] && SCAN_FLAG=1;break || sleep 10
done
 
if [[ ${SCAN_FLAG} -ne 1 ]]; then
       [[ -n `ps aux | grep java | grep broker` ]] && kill -9 `ps aux | grep java | awk '/broker/{print $2}'`
       cd /usr/local/rocketmq/bin && nohup sh mqbroker -c ../conf/2m-noslave/broker-a.properties &
fi

 

 

【注意】

以上紅色標註部分,在master2上的名稱爲「broker-b.properties」

 

4crontab信息添加

# touch /var/run/check_rocketmq_nameserver.lock

# touch /var/run/check_rocketmq_brokerserver.lock

 

# echo 'touch /var/run/check_rocketmq_nameserver.lock' >> /etc/rc.d/rc.local

# echo 'touch /var/run/check_rocketmq_brokerserver.lock' >> /etc/rc.d/rc.local

 

# crontab -e

*/2 * * * * (flock --timeout=0 /var/run/check_rocketmq_nameserver.lock /data/scripts/check_nameserver_health.sh >/dev/null 2>&1)

 

*/2 * * * * (flock --timeout=0 /var/run/check_rocketmq_brokerserver.lock /data/scripts/check_brokerserver_health.sh >/dev/null 2>&1)

 

 

 

消息中間件選型時,要關注哪些問題

消息隊列中間件(簡稱消息中間件)是指利用高效可靠的消息傳遞機制進行與平臺無關的數據交流,並基於數據通訊來進行分佈式系統的集成。經過提供消息傳遞和消息排隊模型,它能夠在分佈式環境下提供應用解耦、彈性伸縮、冗餘存儲、流量削峯、異步通訊、數據同步等等功能,其做爲分佈式系統架構中的一個重要組件,有着舉足輕重的地位。

目前開源的消息中間件可謂是琳琅滿目,能讓你們耳熟能詳的就有不少,好比 ActiveMQ、RabbitMQ、Kafka、RocketMQ、ZeroMQ 等。無論選擇其中的哪一款,都會有用的不趁手的地方,畢竟不是爲你量身定製的。

有些大廠在長期的使用過程當中積累了必定的經驗,其消息隊列的使用場景也相對穩定固化,或者目前市面上的消息中間件沒法知足自身需求,而且也具有足夠的精力和人力而選擇自研來爲本身量身打造一款消息中間件。可是絕大多數公司仍是不會選擇重複造輪子,那麼選擇一款合適本身的消息中間件顯得尤其重要。就算是前者,那麼在自研出穩定且可靠的相關產品以前仍是會經歷這樣一個選型過程。

在總體架構中引入消息中間件,勢必要考慮不少因素,好比成本及收益問題,怎麼樣才能達到最優的性價比?雖然消息中間件種類繁多,可是各自都有各自的側重點,選擇合適本身、揚長避短無疑是最好的方式。若是你對此感到無所適從,本文或許能夠參考一二。

各種消息隊列簡述

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、CKafka,又好比基於 Go 語言的 NSQ,有時人們也把相似 Redis 的產品也看作消息中間件的一種,固然它們都很優秀,可是本文篇幅限制沒法窮極全部,下面會針對性的挑選 RabbitMQ 和 Kafka 兩款典型的消息中間件來作分析,力求站在一個公平公正的立場來闡述消息中間件選型中的各個要點。

選型要點概述

衡量一款消息中間件是否符合需求須要從多個維度進行考察,首要的就是功能維度,這個直接決定了你可否最大程度上的實現開箱即用,進而縮短項目週期、下降成本等。若是一款消息中間件的功能達不到想要的功能,那麼就須要進行二次開發,這樣會增長項目的技術難度、複雜度以及增大項目週期等。

 功能維度

功能維度又能夠劃分個多個子維度,大體能夠分爲如下這些:

優先級隊列

優先級隊列不一樣於先進先出隊列,優先級高的消息具有優先被消費的特權,這樣能夠爲下游提供不一樣消息級別的保證。不過這個優先級也是須要有一個前提的:若是消費者的消費速度大於生產者的速度,而且消息中間件服務器(通常簡單的稱之爲 Broker)中沒有消息堆積,那麼對於發送的消息設置優先級也就沒有什麼實質性的意義了,由於生產者剛發送完一條消息就被消費者消費了,那麼就至關於 Broker 中至多隻有一條消息,對於單條消息來講優先級是沒有什麼意義的。

延遲隊列

當你在網上購物的時候是否會遇到這樣的提示:「三十分鐘以內未付款,訂單自動取消」?這個是延遲隊列的一種典型應用場景。延遲隊列存儲的是對應的延遲消息,所謂「延遲消息」是指當消息被髮送之後,並不想讓消費者馬上拿到消息,而是等待特定時間後,消費者才能拿到這個消息進行消費。延遲隊列通常分爲兩種:基於消息的延遲和基於隊列的延遲。基於消息的延遲是指爲每條消息設置不一樣的延遲時間,那麼每當隊列中有新消息進入的時候就會從新根據延遲時間排序,固然這也會對性能形成極大的影響。實際應用中大多采用基於隊列的延遲,設置不一樣延遲級別的隊列,好比 5s、10s、30s、1min、5mins、10mins 等,每一個隊列中消息的延遲時間都是相同的,這樣免去了延遲排序所要承受的性能之苦,經過必定的掃描策略(好比定時)便可投遞超時的消息。

死信隊列

因爲某些緣由消息沒法被正確的投遞,爲了確保消息不會被無端的丟棄,通常將其置於一個特殊角色的隊列,這個隊列通常稱之爲死信隊列。與此對應的還有一個「回退隊列」的概念,試想若是消費者在消費時發生了異常,那麼就不會對這一次消費進行確認(Ack), 進而發生回滾消息的操做以後消息始終會放在隊列的頂部,而後不斷被處理和回滾,致使隊列陷入死循環。爲了解決這個問題,能夠爲每一個隊列設置一個回退隊列,它和死信隊列都是爲異常的處理提供的一種機制保障。實際狀況下,回退隊列的角色能夠由死信隊列和重試隊列來扮演。

重試隊列

重試隊列其實能夠當作是一種回退隊列,具體指消費端消費消息失敗時,爲防止消息無端丟失而從新將消息回滾到 Broker 中。與回退隊列不一樣的是重試隊列通常分紅多個重試等級,每一個重試等級通常也會設置從新投遞延時,重試次數越多投遞延時就越大。舉個例子:消息第一次消費失敗入重試隊列 Q1,Q1 的從新投遞延遲爲 5s,在 5s 事後從新投遞該消息;若是消息再次消費失敗則入重試隊列 Q2,Q2 的從新投遞延遲爲 10s,在 10s 事後再次投遞該消息。以此類推,重試越屢次從新投遞的時間就越久,爲此須要設置一個上限,超過投遞次數就入死信隊列。重試隊列與延遲隊列有相同的地方,都是須要設置延遲級別,它們彼此的區別是:延遲隊列動做由內部觸發,重試隊列動做由外部消費端觸發;延遲隊列做用一次,而重試隊列的做用範圍會向後傳遞。

消費模式

消費模式分爲推(push)模式和拉(pull)模式。推模式是指由 Broker 主動推送消息至消費端,實時性較好,不過須要必定的流制機制來確保服務端推送過來的消息不會壓垮消費端。而拉模式是指消費端主動向 Broker 端請求拉取(通常是定時或者定量)消息,實時性較推模式差,可是能夠根據自身的處理能力而控制拉取的消息量。

廣播消費

消息通常有兩種傳遞模式:點對點(P2P,Point-to-Point)模式和發佈 / 訂閱(Pub/Sub)模式。對於點對點的模式而言,消息被消費之後,隊列中不會再存儲,因此消息消費者不可能消費到已經被消費的消息。雖然隊列能夠支持多個消費者,可是一條消息只會被一個消費者消費。發佈訂閱模式定義瞭如何向一個內容節點發布和訂閱消息,這個內容節點稱爲主題(topic),主題能夠認爲是消息傳遞的中介,消息發佈者將消息發佈到某個主題,而消息訂閱者則從主題中訂閱消息。主題使得消息的訂閱者與消息的發佈者互相保持獨立,不須要進行接觸便可保證消息的傳遞,發佈 / 訂閱模式在消息的一對多廣播時採用。RabbitMQ 是一種典型的點對點模式,而 Kafka 是一種典型的發佈訂閱模式。可是 RabbitMQ 中能夠經過設置交換器類型來實現發佈訂閱模式而達到廣播消費的效果,Kafka 中也能以點對點的形式消費,你徹底能夠把其消費組(consumer group)的概念當作是隊列的概念。不過對比來講,Kafka 中由於有了消息回溯功能的存在,對於廣播消費的力度支持比 RabbitMQ 的要強。

消息回溯

通常消息在消費完成以後就被處理了,以後不再能消費到該條消息。消息回溯正好相反,是指消息在消費完成以後,還能消費到以前被消費掉的消息。對於消息而言,常常面臨的問題是「消息丟失」,至因而真正因爲消息中間件的缺陷丟失仍是因爲使用方的誤用而丟失通常很難追查,若是消息中間件自己具有消息回溯功能的話,能夠經過回溯消費復現「丟失的」消息進而查出問題的源頭之所在。消息回溯的做用遠不止與此,好比還有索引恢復、本地緩存重建,有些業務補償方案也能夠採用回溯的方式來實現。

消息堆積 + 持久化

流量削峯是消息中間件的一個很是重要的功能,而這個功能其實得益於其消息堆積能力。從某種意義上來說,若是一個消息中間件不具有消息堆積的能力,那麼就不能把它看作是一個合格的消息中間件。消息堆積份內存式堆積和磁盤式堆積。RabbitMQ 是典型的內存式堆積,但這並不是絕對,在某些條件觸發後會有換頁動做來將內存中的消息換頁到磁盤(換頁動做會影響吞吐),或者直接使用惰性隊列來將消息直接持久化至磁盤中。Kafka 是一種典型的磁盤式堆積,全部的消息都存儲在磁盤中。通常來講,磁盤的容量會比內存的容量要大得多,對於磁盤式的堆積其堆積能力就是整個磁盤的大小。從另一個角度講,消息堆積也爲消息中間件提供了冗餘存儲的功能。援引 紐約時報的案例,其直接將 Kafka 用做存儲系統。

消息追蹤

對於分佈式架構系統中的鏈路追蹤(trace)而言,你們必定不會陌生。對於消息中間件而言,消息的鏈路追蹤(如下簡稱消息追蹤)一樣重要。對於消息追蹤最通俗的理解就是要知道消息從哪來,存在哪裏以及發往哪裏去。基於此功能下,咱們能夠對發送或者消費完的消息進行鏈路追蹤服務,進而能夠進行問題的快速定位與排查。

消息過濾

消息過濾是指按照既定的過濾規則爲下游用戶提供指定類別的消息。就以 kafka 而言,徹底能夠將不一樣類別的消息發送至不一樣的 topic 中,由此能夠實現某種意義的消息過濾,或者 Kafka 還能夠根據分區對同一個 topic 中的消息進行分類。不過更加嚴格意義上的消息過濾應該是對既定的消息採起必定的方式按照必定的過濾規則進行過濾。一樣以 Kafka 爲例,能夠經過客戶端提供的 ConsumerInterceptor 接口或者 Kafka Stream 的 filter 功能進行消息過濾。

多租戶

也能夠稱爲多重租賃技術,是一種軟件架構技術,主要用來實現多用戶的環境下公用相同的系統或程序組件,而且仍能夠確保各用戶間數據的隔離性。RabbitMQ 就可以支持多租戶技術,每個租戶表示爲一個 vhost,其本質上是一個獨立的小型 RabbitMQ 服務器,又有本身獨立的隊列、交換器及綁定關係等,而且它擁有本身獨立的權限。vhost 就像是物理機中的虛擬機同樣,它們在各個實例間提供邏輯上的分離,爲不一樣程序安全保密地容許數據,它既能將同一個 RabbitMQ 中的衆多客戶區分開,又能夠避免隊列和交換器等命名衝突。

多協議支持

消息是信息的載體,爲了讓生產者和消費者都能理解所承載的信息(生產者須要知道如何構造消息,消費者須要知道如何解析消息),它們就須要按照一種統一的格式描述消息,這種統一的格式稱之爲消息協議。有效的消息必定具備某種格式,而沒有格式的消息是沒有意義的。通常消息層面的協議有 AMQP、MQTT、STOMP、XMPP 等(消息領域中的 JMS 更多的是一個規範而不是一個協議),支持的協議越多其應用範圍就會越廣,通用性越強,好比 RabbitMQ 可以支持 MQTT 協議就讓其在物聯網應用中得到一席之地。還有的消息中間件是基於其自己的私有協議運轉的,典型的如 Kafka。

跨語言支持

對不少公司而言,其技術棧體系中會有多種編程語言,如 C/C++、JAVA、Go、PHP 等,消息中間件自己具有應用解耦的特性,若是可以進一步的支持多客戶端語言,那麼就能夠將此特性的效能擴大。跨語言的支持力度也能夠從側面反映出一個消息中間件的流行程度。

流量控制

流量控制(flow control)針對的是發送方和接收方速度不匹配的問題,提供一種速度匹配服務抑制發送速率使接收方應用程序的讀取速率與之相適應。一般的流控方法有 Stop-and-wait、滑動窗口以及令牌桶等。

消息順序性

顧名思義,消息順序性是指保證消息有序。這個功能有個很常見的應用場景就是 CDC(Change Data Chapture),以 MySQL 爲例,若是其傳輸的 binlog 的順序出錯,好比本來是先對一條數據加 1,而後再乘以 2,發送錯序以後就變成了先乘以 2 後加 1 了,形成了數據不一致。

安全機制

在 Kafka 0.9 版本以後就開始增長了身份認證和權限控制兩種安全機制。身份認證是指客戶端與服務端鏈接進行身份認證,包括客戶端與 Broker 之間、Broker 與 Broker 之間、Broker 與 ZooKeeper 之間的鏈接認證,目前支持 SSL、SASL 等認證機制。權限控制是指對客戶端的讀寫操做進行權限控制,包括對消息或 Kafka 集羣操做權限控制。權限控制是可插拔的,並支持與外部的受權服務進行集成。對於 RabbitMQ 而言,其一樣提供身份認證(TLS/SSL、SASL)和權限控制(讀寫操做)的安全機制。

消息冪等性

對於確保消息在生產者和消費者之間進行傳輸而言通常有三種傳輸保障(delivery guarantee):At most once,至多一次,消息可能丟失,但毫不會重複傳輸;At least once,至少一次,消息毫不會丟,可是可能會重複;Exactly once,精確一次,每條消息確定會被傳輸一次且僅一次。對於大多數消息中間件而言,通常只提供 At most once 和 At least once 兩種傳輸保障,對於第三種通常很難作到,由此消息冪等性也很難保證。

Kafka 自 0.11 版本開始引入了冪等性和事務,Kafka 的冪等性是指單個生產者對於單分區單會話的冪等,而事務能夠保證原子性地寫入到多個分區,即寫入到多個分區的消息要麼所有成功,要麼所有回滾,這兩個功能加起來可讓 Kafka 具有 EOS(Exactly Once Semantic)的能力。

不過若是要考慮全局的冪等,還須要與從上下游方面綜合考慮,即關聯業務層面,冪等處理自己也是業務層面所須要考慮的重要議題。如下游消費者層面爲例,有可能消費者消費完一條消息以後沒有來得及確認消息就發生異常,等到恢復以後又得從新消費原來消費過的那條消息,那麼這種類型的消息冪等是沒法有消息中間件層面來保證的。若是要保證全局的冪等,須要引入更多的外部資源來保證,好比以訂單號做爲惟一性標識,而且在下游設置一個去重表。

事務性消息

事務自己是一個並不陌生的詞彙,事務是由事務開始(Begin Transaction)和事務結束(End Transaction)之間執行的全體操做組成。支持事務的消息中間件並不在少數,Kafka 和 RabbitMQ 都支持,不過此二者的事務是指生產者發生消息的事務,要麼發送成功,要麼發送失敗。消息中間件能夠做爲用來實現分佈式事務的一種手段,但其自己並不提供全局分佈式事務的功能。

下表是對 Kafka 與 RabbitMQ 功能的總結性對比及補充說明。

 性能

功能維度是消息中間件選型中的一個重要的參考維度,但這並非惟一的維度。有時候性能比功能還要重要,何況性能和功能不少時候是相悖的,魚和熊掌不可兼得,Kafka 在開啓冪等、事務功能的時候會使其性能下降,RabbitMQ 在開啓 rabbitmq_tracing 插件的時候也會極大的影響其性能。消息中間件的性能通常是指其吞吐量,雖然從功能維度上來講,RabbitMQ 的優點要大於 Kafka,可是 Kafka 的吞吐量要比 RabbitMQ 高出 1 至 2 個數量級,通常 RabbitMQ 的單機 QPS 在萬級別以內,而 Kafka 的單機 QPS 能夠維持在十萬級別,甚至能夠達到百萬級。

消息中間件的吞吐量始終會受到硬件層面的限制。就以網卡帶寬爲例,若是單機單網卡的帶寬爲 1Gbps,若是要達到百萬級的吞吐,那麼消息體大小不得超過 (1Gb/8)/100W,即約等於 134B,換句話說若是消息體大小超過 134B,那麼就不可能達到百萬級別的吞吐。這種計算方式一樣能夠適用於內存和磁盤。

時延做爲性能維度的一個重要指標,卻每每在消息中間件領域所被忽視,由於通常使用消息中間件的場景對時效性的要求並非很高,若是要求時效性徹底能夠採用 RPC 的方式實現。消息中間件具有消息堆積的能力,消息堆積越大也就意味着端到端的時延也就越長,與此同時延時隊列也是某些消息中間件的一大特點。那麼爲何還要關注消息中間件的時延問題呢?消息中間件可以解耦系統,對於一個時延較低的消息中間件而言,它可讓上游生產者發送消息以後能夠迅速的返回,也可讓消費者更加快速的獲取到消息,在沒有堆積的狀況下可讓總體上下游的應用之間的級聯動做更加高效,雖然不建議在時效性很高的場景下使用消息中間件,可是若是所使用的消息中間件的時延方面比較優秀,那麼對於總體系統的性能將會是一個不小的提高。

 可靠性 + 可用性

消息丟失是使用消息中間件時所不得不面對的一個同點,其背後消息可靠性也是衡量消息中間件好壞的一個關鍵因素。尤爲是在金融支付領域,消息可靠性尤其重要。然而說到可靠性必然要說到可用性,注意這二者之間的區別,消息中間件的可靠性是指對消息不丟失的保障程度;而消息中間件的可用性是指無端障運行的時間百分比,一般用幾個 9 來衡量。

從狹義的角度來講,分佈式系統架構是一致性協議理論的應用實現,對於消息可靠性和可用性而言也能夠追溯到消息中間件背後的一致性協議。對於 Kafka 而言,其採用的是相似 PacificA 的一致性協議,經過 ISR(In-Sync-Replica)來保證多副本之間的同步,而且支持強一致性語義(經過 acks 實現)。對應的 RabbitMQ 是經過鏡像環形隊列實現多副本及強一致性語義的。多副本能夠保證在 master 節點宕機異常以後能夠提高 slave 做爲新的 master 而繼續提供服務來保障可用性。Kafka 設計之初是爲日誌處理而生,給人們留下了數據可靠性要求不要的不良印象,可是隨着版本的升級優化,其可靠性獲得極大的加強,詳細能夠參考 KIP101。就目前而言,在金融支付領域使用 RabbitMQ 居多,而在日誌處理、大數據等方面 Kafka 使用居多,隨着 RabbitMQ 性能的不斷提高和 Kafka 可靠性的進一步加強,相信彼此都能在之前不擅長的領域分得一杯羹。

同步刷盤是加強一個組件可靠性的有效方式,消息中間件也不例外,Kafka 和 RabbitMQ 均可以支持同步刷盤,可是筆者對同步刷盤有必定的疑問:絕大多數情景下,一個組件的可靠性不該該由同步刷盤這種極其損耗性能的操做來保障,而是採用多副本的機制來保證。

這裏還要說起的一個方面是擴展能力,這裏我狹隘地將此概括到可用性這一維度,消息中間件的擴展能力可以加強其用可用能力及範圍,好比前面提到的 RabbitMQ 支持多種消息協議,這個就是基於其插件化的擴展實現。還有從集羣部署上來說,歸功於 Kafka 的水平擴展能力,其基本上能夠達到線性容量提高的水平,在 LinkedIn 實踐介紹中就說起了有部署超過千臺設備的 Kafka 集羣。

 運維管理

在消息中間件的使用過程當中不免會出現各式各樣的異常狀況,有客戶端的,也有服務端的,那麼怎樣及時有效的進行監測及修復。業務線流量有峯值又低谷,尤爲是電商領域,那麼怎樣前進行有效的容量評估,尤爲是大促期間?腳踢電源、網線被挖等事件層出不窮,如何有效的作好異地多活?這些都離不開消息中間件的衍生產品——運維管理。

運維管理也能夠進行進一步的細分,好比:申請、審覈、監控、告警、管理、容災、部署等。

申請、審覈很好理解,在源頭對資源進行管控,既能夠進行有效校訂應用方的使用規範,配和監控也能夠作好流量統計與流量評估工做,通常申請、審覈與公司內部系統交融性較大,不適合使用開源類的產品。

監控、告警也比較好理解,對消息中間件的使用進行全方位的監控,便可覺得系統提供基準數據,也能夠在檢測到異常的狀況配合告警,以便運維、開發人員的迅速介入。除了通常的監控項(好比硬件、GC 等)以外,對於消息中間件還須要關注端到端時延、消息審計、消息堆積等方面。對於 RabbitMQ 而言,最正統的監控管理工具莫過於 rabbitmq_management 插件了,可是社區內還有 AppDynamics, Collectd, DataDog, Ganglia, Munin, Nagios, New Relic, Prometheus, Zenoss 等多種優秀的產品。Kafka 在此方面也絕不遜色,好比:Kafka Manager, Kafka Monitor, Kafka Offset Monitor, Burrow, Chaperone, Confluent Control Center 等產品,尤爲是 Cruise 還能夠提供自動化運維的功能。

無論是擴容、降級、版本升級、集羣節點部署、仍是故障處理都離不開管理工具的應用,一個配套完備的管理工具集能夠在遇到變動時作到事半功倍。故障可大可小,通常是一些應用異常,也能夠是機器掉電、網絡異常、磁盤損壞等單機故障,這些故障單機房內的多副本足以應付。若是是機房故障就要涉及異地容災了,關鍵點在於如何有效的進行數據複製,對於 Kafka 而言,能夠參考 MirrorMarker、uReplicator 等產品,而 RabbitMQ 能夠參考 Federation 和 Shovel。

 社區力度及生態發展

對於目前流行的編程語言而言,如 Java、Python,若是你在使用過程當中遇到了一些異常,基本上能夠經過搜索引擎的幫助來獲得解決,由於一個產品用的人越多,踩過的坑也就越多,對應的解決方案也就越多。對於消息中間件也一樣適用,若是你選擇了一種「生僻」的消息中間件,可能在某些方面運用的駕輕就熟,可是版本更新緩慢、遇到棘手問題也難以獲得社區的支持而越陷越深;相反若是你選擇了一種「流行」的消息中間件,其更新力度大,不只能夠迅速的彌補以前的不足,並且也能順應技術的快速發展來變動一些新的功能,這樣可讓你以「站在巨人的肩膀上」。在運維管理維度咱們說起了 Kafka 和 RabbitMQ 都有一系列開源的監控管理產品,這些正是得益於其社區及生態的迅猛發展。

消息中間件選型誤區探討

在進行消息中間件選型以前能夠先問本身一個問題:是否真的須要一個消息中間件?在搞清楚這個問題以後,還能夠繼續問本身一個問題:是否須要本身維護一套消息中間件?不少初創型公司爲了節省成本會選擇直接購買消息中間件有關的雲服務,本身只須要關注收發消息便可,其他的均可之外包出去。

不少人面對消息中間件時會有一種自研的衝動,你徹底能夠對 Java 中的 ArrayBlockingQueue 作一個簡單的封裝,你也能夠基於文件、數據庫、Redis 等底層存儲封裝而造成一個消息中間件。消息中間件作爲一個基礎組件並無想象中的那麼簡單,其背後還須要配套的管理運維整個生態的產品集。自研還有會交接問題,若是文檔不齊全、運做不規範將會帶給新人噩夢般的體驗。是否真的有自研的必要?若是不是 KPI 的壓迫能夠先考慮下這 2 個問題:1. 目前市面上的消息中間件是否都真的沒法知足目前業務需求? 2. 團隊是否有足夠的能力、人力、財力、精力來支持自研?

不少人在作消息中間件選型時會參考網絡上的不少對比類的文章,可是其專業性、嚴謹性、以及其政治立場問題都有待考證,須要帶着懷疑的態度去審視這些文章。好比有些文章會在沒有任何限定條件及場景的狀況下直接定義某款消息中間件最好,還有些文章沒有指明消息中間件版本及測試環境就來作功能和性能對比分析,諸如此類的文章均可以唾棄之。

消息中間件猶如小馬過河,選擇合適的才最重要,這須要貼合自身的業務需求,技術服務於業務,大致上能夠根據上一節所說起的功能、性能等 6 個維度來一一進行篩選。更深層次的抉擇在於你可否掌握其魂,筆者鄙見:RabbitMQ 在於 routing,而 Kafka 在於 streaming,瞭解其根本對於本身可以對症下藥選擇到合適的消息中間件尤其重要。

消息中間件選型切忌一味的追求性能或者功能,性能能夠優化,功能能夠二次開發。若是要在功能和性能方面作一個抉擇的話,那麼首選性能,由於整體上來講性能優化的空間沒有功能擴展的空間大。然而對於長期發展而言,生態又比性能以及功能都要重要。

不少時候,對於可靠性方面也容易存在一個誤區:想要找到一個產品來保證消息的絕對可靠,很不幸的是這世界上沒有絕對的東西,只能說盡可能趨於完美。想要儘量的保障消息的可靠性也並不是單單隻靠消息中間件自己,還要依賴於上下游,須要從生產端、服務端和消費端這 3 個維度去努力保證,《RabbitMQ 消息可靠性分析》這篇文章就從這 3 個維度去分析了 RabbitMQ 的可靠性。

消息中間件選型還有一個考量標準就是儘可能貼合團隊自身的技術棧體系,雖說沒有蹩腳的消息中間件只有蹩腳的程序員,可是讓一個 C 棧的團隊去深挖 PhxQueue 總比去深挖 Scala 編寫的 Kafka 要容易的多。

消息中間件大道至簡:一發一存一消費,沒有最好的消息中間件,只有最合適的消息中間件。

相關文章
相關標籤/搜索