官網文檔參考地址:http://rocketmq.apache.org/docs/motivation/
安裝包下載地址:https://mirror.bit.edu.cn/apache/rocketmq/4.7.0/rocketmq-all-4.7.0-bin-release.zip
https://mirrors.tuna.tsinghua.edu.cn/apache/rocketmq/4.7.0/rocketmq-all-4.7.0-bin-release.zip
1,什麼是 RocketMQ?
Apache RocketMQ是由阿里巴巴開源的可支撐萬億級數據洪峯的分佈式消息和流計算平臺,於2016年捐贈給Apache Software Foundation,2017年9月25日成爲Apache 頂級項目。由於其高穩定性、低延時、高吞吐量等特點,被大規模應用於金融、互聯網、物流公司的核心交易支付、實時位置追蹤、大數據分析等場景,同時也被電力、交通、汽車、零售等十幾個行業的數萬家企業廣泛使用,是企業數字化轉型的核心基礎性軟件。
如圖所示爲RocketMQ基本的部署結構,主要分爲NameServer集羣、Broker集羣、Producer集羣和Consumer集羣四個部分。
NameServer集羣
NameServer的作用是註冊中心,類似於Zookeeper,但又有區別於它的地方。每個NameServer節點互相之間是獨立的,沒有任何信息交互,也就不存在任何的選主或者主從切換之類的問題,因此NameServer與Zookeeper相比更輕量級。單個NameServer節點中存儲了活躍的Broker列表(包括master和slave),這裏活躍的定義是與NameServer保持有心跳。
Broker集羣
Broker是具體提供業務的服務器,單個Broker節點與所有的NameServer節點保持長連接及心跳,並會定時將Topic信息註冊到NameServer,順帶一提底層的通信和連接都是基於Netty實現的。
Broker中分master和slave兩種角色,每個master可以對應多個slave,但一個slave只能對應一個master,master和slave通過指定相同的Brokername,不同的BrokerId (master爲0)成爲一個組。master和slave之間的同步方式分爲同步雙寫和異步複製,異步複製方式master和slave之間雖然會存在少量的延遲,但性能較同步雙寫方式要高出10%左右。
Producer集羣
與nameserver的關係:
單個Producer和一臺nameserver保持長連接,定時查詢topic配置信息,如果該nameserver掛掉,生產者會自動連接下一個nameserver,直到有可用連接爲止,並能自動重連。與nameserver之間沒有心跳。
與broker的關係:
單個Producer和與其關聯的所有broker保持長連接,並維持心跳。默認情況下消息發送採用輪詢方式,會均勻發到對應Topic的所有queue中。
最佳實踐:
一個應用儘可能只使用一個 Topic,消息子類型用 tags 來標識,tags 可以由應用自由設置。只有發送消息設置了tags,消費方在訂閱消息時,纔可以利用 tags 在 broker 做消息過濾。每個消息在業務層面的唯一標識碼,要設置到 keys 字段,方便將來定位消息丟失問題。服務器會爲每個消
息創建索引(哈希索引),應用可以通過 Topic,key 來查詢返條消息內容,以及消息被誰消費。由於是哈希索引,請務必保證 key 儘可能唯一,這樣可以避免潛在的哈希衝突。消息發送成功或者失敗,要打印消息日誌,務必要打印 sendresult 和 key 字段。對於消息不可丟失應用,務必要有消息
重發機制。例如:消息發送失敗,存儲到數據庫,能有定時程序嘗試重發或者人工觸發重發。某些應用如果不關注消息是否發送成功,請直接使用sendOneWay方法發送消息。
Consumer集羣
與nameserver的關係:
單個Consumer和一臺nameserver保持長連接,定時查詢topic配置信息,如果該nameserver掛掉,消費者會自動連接下一個nameserver,直到有可用連接爲止,並能自動重連。與nameserver之間沒有心跳。
與broker的關係:
單個Consumer和與其關聯的所有broker保持長連接,並維持心跳,失去心跳後,則關閉連接,並向該消費者分組的所有消費者發出通知,分組內消費者重新分配隊列繼續消費。
最佳實踐:
Consumer 數量要小於等於queue的總數量,由於Topic下的queue會被相對均勻的分配給Consumer,如果 Consumer 超過queue的數量,那多餘的 Consumer 將沒有queue可以消費消息。
消費過程要做到冪等(即消費端去重),RocketMQ爲了保證性能並不支持嚴格的消息去重。
儘量使用批量方式消費,RocketMQ消費端採用pull方式拉取消息,通過consumeMessageBatchMaxSize參數可以增加單次拉取的消息數量,可以很大程度上提高消費吞吐量。另外,提高消費並行度也可以通過增加Consumer處理線程的方式,對應參數consumeThreadMin和consumeThreadMax。
消息發送成功或者失敗,要打印消息日誌。
Topic和Queue
RocketMQ的Topic/Queue和JMS中的Topic/Queue概念有一定的差異,JMS中所有消費者都會消費一個Topic消息的副本,而Queue中消息只會被一個消費者消費;但到了RocketMQ中Topic只代表普通的消息隊列,而Queue是組成Topic的更小單元,集羣消費模式下一個消費者只消費該Topic中部分Queue中的消息,當一個消費者開啓廣播模式時則會消費該Topic下所有Queue中的消息。Topic和Queue的具體關係可以參考下圖
2,爲什麼選擇RocketMQ
特色功能
彈性擴縮:
Brokers, producers, consumers, name servers都採用了特殊的部署和處理方式,具備很強的橫向擴展能力。
分佈式事務:
RocketMQ實現類似X/Open XA的分佈事務功能,以達到事務最終一致性狀態。
快速存儲和持久化:
RocketMQ充分利用了系統的內存cache,數據以同步或者異步刷盤的方式持久化到文件系統中。
消息過濾:
Apache RocketMQ支持靈活的語法表達式過濾消息,減少了對於consumer無用消息的網絡傳輸。
回溯消費:
基於Apache RocketMQ的數據存儲方式,consumer可以實現按照時間回溯消費,精確到毫秒,支持向前回溯和向後回溯。
定時消息:
Apache RocketMQ支持定時消息,但是不支持任意時間精度,具有特定的level。
下表是官網給出的RocketMQ,ActiveMQ和Kafka(根據awesome-java,Apache最流行的消息傳遞解決方案)之間的比較:
Messaging Product |
Client SDK |
Protocol and Specification |
Ordered Message |
Scheduled Message |
Batched Message |
BroadCast Message |
Message Filter |
Server Triggered Redelivery |
Message Storage |
Message Retroactive |
Message Priority |
High Availability and Failover |
Message Track |
Configuration |
Management and Operation Tools |
ActiveMQ |
Java, .NET, C++ etc. |
Push model, support OpenWire, STOMP, AMQP, MQTT, JMS |
Exclusive Consumer or Exclusive Queues can ensure ordering |
Supported |
Not Supported |
Supported |
Supported |
Not Supported |
Supports very fast persistence using JDBC along with a high performance journal,such as levelDB, kahaDB |
Supported |
Supported |
Supported, depending on storage,if using kahadb it requires a ZooKeeper server |
Not Supported |
The default configuration is low level, user need to optimize the configuration parameters |
Supported |
Kafka |
Java, Scala etc. |
Pull model, support TCP |
Ensure ordering of messages within a partition |
Not Supported |
Supported, with async producer |
Not Supported |
Supported, you can use Kafka Streams to filter messages |
Not Supported |
High performance file storage |
Supported offset indicate |
Not Supported |
Supported, requires a ZooKeeper server |
Not Supported |
Kafka uses key-value pairs format for configuration. These values can be supplied either from a file or programmatically. |
Supported, use terminal command to expose core metrics |
RocketMQ |
Java, C++, Go |
Pull model, support TCP, JMS, OpenMessaging |
Ensure strict ordering of messages,and can scale out gracefully |
Supported |
Supported, with sync mode to avoid message loss |
Supported |
Supported, property filter expressions based on SQL92 |
Supported |
High performance and low latency file storage |
Supported timestamp and offset two indicates |
Not Supported |
Supported, Master-Slave model, without another kit |
Supported |
Work out of box,user only need to pay attention to a few configurations |
Supported, rich web and terminal command to expose core metrics |
個人總結概括一下當下幾個常用消息隊列中間件的對比:
國內採用的MQ有:ActiveMQ、Kafka、RabbitMQ、RocketMQ,但現在ActiveMQ用的越來越少了。主要做其他三種的調研。
kafka:
- 1、開發語言: Scala開發
- 2、性能、吞吐量: 吞吐量所有MQ裏最優秀,QPS十萬級、性能毫秒級、支持集羣部署
- 3、功能: 功能單一
- 4、缺點: 丟數據, 因爲數據先寫入磁盤緩衝區,未直接落盤。機器故障會造成數據丟失
- 5、應用場景: 適當丟失數據沒有關係、吞吐量要求高、不需要太多的高級功能的場景,比如大數據場景。
RabbitMQ:
- 1、開發語言: Erlang開發
- 2、性能、吞吐量: 吞吐量比較低,QPS幾萬級、性能u秒級、主從架構
- 3、功能: 功能單一
- 4、缺點: Erlang小衆語言開發,吞吐量低,集羣擴展麻煩
- 5、應用場景: 中小公司對併發和吞吐量要求不高的場景。
RocketMQ:
- 1、開發語言: java開發
- 2、性能、吞吐量: 吞吐量高,QPS十萬級、性能毫秒級、支持集羣部署
- 3、功能: 支持各種高級功能,比如說延遲消息、事務消息、消息回溯、死信隊列、消息積壓等等
- 4、缺點: 官方文檔相對簡單可能是RocketMQ目前唯一的缺點
- 5、應用場景: 適當丟失數據沒有關係、吞吐量要求高、不需要太多的高級功能的場景,比如大數據場景。
3,安裝部署
從下載鏈接下載安裝包:rocketmq-all-4.7.0-bin-release.zip 並解壓
1) 單Master模式
這種方式風險較大,一旦Broker重啓或者宕機時,會導致整個服務不可用。不建議線上環境使用,可以用於本地測試。
1 啓動 NameServer:
$ nohup ${ROCKETMQ_HOME}/bin/mqnamesrv &
### 驗證Name Server 是否啓動成功
$ tail -f ~/logs/rocketmqlogs/namesrv.log
The Name Server boot success...
2 啓動 Broker:
### 啓動Broker
$ nohup $ROCKETMQ_HOME/bin/mqbroker -n localhost:9876 &
### 驗證Name Server 是否啓動成功,例如Broker的IP爲:192.168.1.2,且名稱爲broker-a
$ tail -f ~/logs/rocketmqlogs/broker.log
The broker[broker-a, 192.169.2.200:10911] boot success...
3 發送和接收消息測試:
在發送/接收消息之前,我們需要告訴客戶端名稱服務器的位置。 RocketMQ提供了多種方法來實現這一目標。 爲簡單起見,我們使用環境變量NAMESRV_ADDR
> export NAMESRV_ADDR=localhost:9876
> sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
SendResult [sendStatus=SEND_OK, msgId= ...
> sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
ConsumeMessageThread_%d Receive New Messages: [MessageExt...
2 多Master模式(這種方式一般使用比較多)
一個集羣無Slave,全是Master,例如2個Master或者3個Master,這種模式的優缺點如下:
- 優點:配置簡單,單個Master宕機或重啓維護對應用無影響,在磁盤配置爲RAID10時,即使機器宕機不可恢復情況下,由於RAID10磁盤非常可靠,消息也不會丟(異步刷盤丟失少量消息,同步刷盤一條不丟),性能最高;
- 缺點:單臺機器宕機期間,這臺機器上未被消費的消息在機器恢復之前不可訂閱,消息實時性會受到影響。
1 啓動NameServer
NameServer需要先於Broker啓動,且如果在生產環境使用,爲了保證高可用,建議一般規模的集羣啓動3個NameServer,各節點的啓動命令相同,如下:
### 首先啓動Name Server
$ nohup sh mqnamesrv &
### 驗證Name Server 是否啓動成功
$ tail -f ~/logs/rocketmqlogs/namesrv.log
The Name Server boot success...
2 啓動Broker集羣
### 在機器A,啓動第一個Master(broker-a),例如NameServer的IP爲:192.168.2.200
修改配置文件:$ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties 增加如下配置項
maxMessageSize = 4194304 #默認允許的最大消息體默認4M
sendMessageThreadPoolNums = 20 # 服務端處理消息發送線程池數量 默認就1個
useReentrantLockWhenPutMessage = true #消息存儲到commitlog文件時獲取鎖類型,如果爲true使用ReentrantLock否則使用自旋鎖
listenPort = 10911 #服務端監聽端口,默認10911;如果在同一個機器啓多個broker是這個必須修改爲不一樣
storePathRootDir = /app/merce/rocketmq/rocketmq/store/broker_a #broker存儲目錄 默認爲用戶的家目錄/store;如果在同一個機器啓多個broker是這個必須修改爲不一樣
storePathCommitLog =/app/merce/rocketmq/rocketmq/store/commitlog #storePathCommitLog 需要單獨配置一次不然無法自動寫入到${storePathRootDir }/commitlog 下,這個是4.7版本的一個bug
啓動broker:
$ nohup ${ROCKETMQ_HOME}/bin/mqbroker -n localhost:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties &
### 在機器B,啓動第二個Master(broker-b)也需要先修改配置文件$ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties,NameServer的IP爲:localhost
$ nohup ${ROCKETMQ_HOME}/bin/mqbroker -n localhost:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties &
如上啓動命令是在單個NameServer情況下使用的。對於多個NameServer的集羣,Broker啓動命令中-n後面的地址列表用分號隔開即可,例如 192.168.1.1:9876;192.161.2:9876。
更多安裝方式如多Master多Slave模式-異步複製,多Master多Slave模式-同步雙寫可參考官網文檔。
配置文件修改:
上邊所說的兩種安裝方式均是使用的系統缺省配置
注意:
1)啓動nameServer 或brocker時如果不使用 -c 指定配置文件,則系統會使用參數的確實值;如果修改了相關配置文件必須在啓動時指定通過 -c 指定配置文件。
2)RocketMq啓動後輸出日誌和相關數據存儲目錄會默認放到當前用戶家目錄下:
- log: ~/logs/rocketmqlogs
如果需要修改logs路徑,比如修改到/app/rocketmq/logs :
$ cd ${ROCKETMQ_HOME}/conf
$ sed -i 's#${user.home}#/app/rocketmq/logs#g' *.xml
- data: ~/store
如果需要修改,比如修改到 /app/rocketmq/store ,需要在對應broker配置文件如 ${ROCKETMQ_HOME}/conf/2m-noslave/broker-a.properties中添加如下配置:storePathRootDir = /app/rocketmq/store
- storePathCommitLog: ~/store/commitlog
需要注意 rocketmq-4.7.0參數storePathCommitLog需要單獨修改,如果只修改storePathRootDir 則commitlog的存儲路徑不會向文檔裏說的自動修改到${storePathRootDir}/commitlog。
修改配置 storePathCommitLog =/app/rocketmq/store/commitlog
3)默認情況下nameserver和brocker分配內存比較大,分別是4G和8G ;如果需要進行調整,需要分別修改下面兩個啓動腳本的參數:
NameServer : runserver.sh
JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
Broker : runbroker.sh
JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g"
4) RocketMq運行發送的messageBody默認情況下超過4K會自動進行壓縮,但壓縮後最大默認情況下也不允許超過4M,如果需要調大改配置參數,需要在brock端和producer 端同時進行配置,
brocker端配置參數:maxMessageSize
producer端 我們platform已經預製了該參數,默認值4194304(4M) 如需修改可通過配置文件platform_home/conf/woven.properties 修改參數:rocketmq.producer.max-message-size 對應值即可.
4,RocketMq管理工具 rocketmq-console
rocketmq-console是apache/rocketmq-externals 下的一個子項目,可以通過圖形界面便捷的監控管理RocketMQ的相關信息。
下載地址:
該工具需要自己下載代碼進行編譯:https://github.com/apache/rocketmq-externals/tree/master/rocketmq-console
安裝方式:
下載後是一個可直接啓動的spring-boot jar,使用如下命令啓動
nohup java -jar rocketmq-console-ng-1.0.1.jar --server.port=12581 --rocketmq.config.namesrvAddr=localhost:9876 &
啓動後通過瀏覽器訪問:http://ip-adderss:12581
特別說明:
目前Apache 官方提供的rocketmq-console源碼裏還不支持brocker端開啓accessKey權限認證,所以如果想要支持可以通過 https://download.csdn.net/download/qq_31910941/12440083 下載,這個是我自己在源碼里加入了該功能編譯的jar;可通過如下命令進行運行:
java -jar rocketmq-console-ng-1.0.1.jar --server.port=12581 --rocketmq.config.namesrvAddr=localhost:9876 --rocketmq.config.accessKey=rocketmq --rocketmq.config.secretKey=87654321