RocketMQ(二)——叢集部署
在Metaq1.x/2.x的版本中,分散式協調採用的是Zookeeper,而RocketMQ自己實現了一個NameServer,所以RocketMQ啟動時,先啟動對應的NameServer。
叢集部署方式
RocketMQ部署比較靈活,推薦幾種Broker的叢集部署方式。
1. 單個Master
很顯然,這種方式風險較大,一旦Broker重啟或者宕機時,會導致整個服務不可用,不建議線上環境使用。
2. 多Master模式
一個叢集無Slave,全是Master,例如2個Master或者3個Master
- 優點:配置簡單,單個Master宕機或重啟維護對應用無影響,在磁碟配置為RAID10時,即使機器宕機不可恢復情況下,由於RAID10磁碟非常可靠,訊息也不會丟(非同步刷盤丟失少量訊息,同步刷盤一條不丟)。效能最高。
- 缺點:單臺機器宕機期間,這臺機器上未被消費的訊息在機器恢復之前不可訂閱,訊息實時性會受到影響。
3. 多Master多Slave模式,非同步複製
每個Master配置一個Slave,有多對Master-Slave,HA採用非同步複製方式,主備有短暫訊息延遲,毫秒級。
- 優點:即使磁碟損壞,訊息丟失的非常少,且訊息實時性不會受影響,因為Master宕機後,消費者仍然可以從Slave消費,此過程對應用透明,不需要人工干預。效能同多Master模式幾乎一樣。
- 缺點:Master宕機,磁碟損壞情況,會丟失少量訊息。
4. 多Master多Slave模式,同步雙寫
每個Master配置一個Slave,有多對Master-Slave,HA採用同步雙寫方式,主備都寫成功,嚮應用返回成功。
- 優點:資料與服務都無單點,Master宕機情況下,訊息無延遲,服務可用性與資料可用性都非常高。
- 缺點:效能比非同步複製模式略低,大約低10%左右,傳送單個訊息的RT會略高。
物理部署結構
以多Master多Slave模式為例,看一下RocketMQ物理部署結構:
- NameServer
NameServer是一個幾乎無狀態節點,可叢集部署,節點之間無任何資訊同步。
- Broker
Broker 部署相對複雜,Broker分為Master和Slave,一個Master可以對應多個Slave,但是一個Slave只能對應一個Master,Master與Slave的對應關係通過指定相同的BrokerName,不同的BrokerId來定義,BrokerId為0表示Master,非0表示Slave。Master也可以部署多個。每個Broker與NameServer叢集中的所有節點建立長連線,定時註冊 Topic 資訊到所有 NameServer。
- Producer
Producer與NameServer叢集中的其中一個節點(隨機選擇)建立長連線,定期從NameServer取Topic路由資訊,並向提供Topic服務的Master建立長連線,且定時向Master傳送心跳。Producer完全無狀態,可叢集部署。
- Consumer
Consumer與NameServer叢集中的其中一個節點(隨機選擇)建立長連線,定期從NameServer取Topic路由資訊,並向提供Topic服務的Master、Slave建立長連線,且定時向Master、Slave傳送心跳。Consumer既可以從Master訂閱訊息,也可以從Slave訂閱訊息,訂閱規則由Broker配置決定。
雙主叢集部署
這裡就以雙主叢集為例,進行搭建。(雙主叢集會部署搭建,多主或多主多從也自然沒啥問題了)
1. 伺服器環境
如果條件允許,NameServer和broker分別在單獨的機器上部署,我是用自己的電腦建的虛擬機器,在虛擬機器中部署的,限於自己電腦的配置,NameServer和broker就放在一臺機器上了。
序號 | IP | 角色 | 模式 |
---|---|---|---|
1 | 192.168.2.222 | nameServer1,brokerServer1 | Master1 |
1 | 192.168.2.223 | nameServer2,brokerServer2 | Master2 |
2. 配置IP對映
其實是可以不配的,為了部署方便起見,我反正配置了。在下面的檔案中配置:
# vi /etc/hosts
IP | NAME |
---|---|
192.168.2.222 | ocketmq-nameserver-1 |
192.168.2.222 | rocketmq-master-1 |
192.168.2.223 | rocketmq-nameserver-2 |
192.168.2.223 | rocketmq-master-2 |
3. 上傳解壓
這裡沒有用最新版的RocketMQ,而是比較經典的3.2.6版本,兩臺機器執行相同的操作。
首先上傳alibaba-rocketmq-3.2.6.tar.gz檔案至/usr/local,然後進行解壓。為了操作方便,這裡建立了軟連線:
# tar -zxvf alibaba-rocketmq-3.2.6.tar.gz -C /usr/local
# mv alibaba-rocketmq alibaba-rocketmq-3.2.6
# ln -s alibaba-rocketmq-3.2.6 rocketmq
4. 建立儲存路徑
兩臺機器執行相同的操作:
# mkdir -p rocketmq/store/{commitlog,consumequeue,index}
5. 修改配置檔案(替換成以下內容)
兩臺機器執行相同的操作,並注意,brokerName的值跟配置檔案一致:
# vim /usr/local/rocketmq/conf/2m-noslave/broker-a.properties
# vim /usr/local/rocketmq/conf/2m-noslave/broker-b.properties
這裡把常用的引數配置基本都列了出來,具體意思在註釋裡:
#所屬叢集名字
brokerClusterName=rocketmq-cluster
#broker名字,注意此處不同的配置檔案填寫的不一樣
brokerName=broker-a|broker-b
#0 表示 Master,>0 表示 Slave
brokerId=0
#nameServer地址,分號分割
namesrvAddr=rocketmq-nameserver1:9876;rocketmq-nameserver2:9876
# 在傳送訊息時,自動建立伺服器不存在的topic,預設建立的佇列數
defaultTopicQueueNums=4
# 是否允許 Broker 自動建立Topic,建議線下開啟,線上關閉
autoCreateTopicEnable=true
# 是否允許 Broker 自動建立訂閱組,建議線下開啟,線上關閉
autoCreateSubscriptionGroup=true
# Broker 對外服務的監聽埠
listenPort=10911
# 刪除檔案時間點,預設凌晨 4點
deleteWhen=04
#檔案保留時間,預設 48 小時
fileReservedTime=120
#commitLog每個檔案的大小預設1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每個檔案預設存30W條,根據業務情況調整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#檢測物理檔案磁碟空間
diskMaxUsedSpaceRatio=88
#儲存路徑
storePathRootDir= /usr/local/rocketmq/store
#commitLog 儲存路徑
storePathCommitLog= /usr/local/rocketmq/store /commitlog
#消費佇列儲存路徑儲存路徑
storePathConsumeQueue=/usr/local/rocketmq/store/consumequeue
#訊息索引儲存路徑
storePathIndex=/usr/local/rocketmq/store/index
#checkpoint 檔案儲存路徑
storeCheckpoint=/usr/local/rocketmq/store/checkpoint
#abort 檔案儲存路徑
abortFile=/usr/local/rocketmq/store/abort
#限制的訊息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#Broker 的角色
#- ASYNC_MASTER 非同步複製Master
#- SYNC_MASTER 同步雙寫Master
#- SLAVE
brokerRole=ASYNC_MASTER
#刷盤方式
#- ASYNC_FLUSH 非同步刷盤
#- SYNC_FLUSH 同步刷盤
flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false
#發訊息執行緒池數量
#sendMessageThreadPoolNums=128
#拉訊息執行緒池數量
#pullMessageThreadPoolNums=128
6. 修改日誌配置檔案
修改日誌配置檔案的目錄,兩臺機器執行相同的操作:
# mkdir -p /usr/local/rocketmq/logs
# cd /usr/local/rocketmq/conf && sed -i 's#${user.home}#/usr/local/rocketmq#g' *.xml
7. 修改啟動指令碼引數
調一下JVM,包括nameserver 和 broker。限於自己機器的配置,引數調小一下。但Rocketmq最少的堆是1g,否則無法啟動。兩臺機器執行相同的操作。
開啟一下runbroker配置檔案:
# vim /usr/local/rocketmq/bin/runbroker.sh
修改內容如下:
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn512m -
XX:PermSize=128m -XX:MaxPermSize=320m"
開啟一下runserver配置檔案:
# vim /usr/local/rocketmq/bin/runserver.sh
修改內容如下:
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn512m -
XX:PermSize=128m -XX:MaxPermSize=320m"
8. 啟動
要先啟動namerserver,再啟broker,兩臺機器執行相同的操作。
啟動nameserver
# cd /usr/local/rocketmq/bin
# nohup sh mqnamesrv &
啟動brokerserver(節點1用的是a.properties,節點2用的是b.properties)
# cd /usr/local/rocketmq/bin
# nohup sh mqbroker -c /usr/local/rocketmq/conf/2m-noslave/broker-a.properties >/dev/null 2>&1 &
# netstat -ntlp
用下面命令檢視一下
# jps
可以用下面命令檢視一下啟動日誌:
# tail -f -n 500 /usr/local/rocketmq/logs/rocketmqlogs/broker.log
# tail -f -n 500 /usr/local/rocketmq/logs/rocketmqlogs/namesrv.log
9. 部署管控臺
在tomcat中部署rocketmq-console.war,修改WEB-INF/classes/config.properties:
啟動管控臺,看一下首頁:
介面比較簡潔,最好進入Topic介面進行mqadmin操作命令:
10. 資料清理
首先停一下服務:
# cd /usr/local/rocketmq/bin
# sh mqshutdown broker
# sh mqshutdown namesrv
然後清一下store,但別忘記重新建一下:
# rm -rf /usr/local/rocketmq/store
# mkdir /usr/local/rocketmq/store
# mkdir /usr/local/rocketmq/store/commitlog
# mkdir /usr/local/rocketmq/store/consumequeue
# mkdir /usr/local/rocketmq/store/index
PS:
- 如果要搭主從,再次重申一遍Master與Slave在配置中的區別
Broker與Slave配對是通過指定相同的brokerName引數來配對,Master的BrokerId 必須是0,Slave的BrokerId必須是大於0的數。另外一個Master下面可以掛載多個Slave,同一Master下的多個Slave 通過指定不同的BrokerId來區分。
- Broker 重啟對客戶端的影響
Broker 重啟可能會導致正在發往這臺機器的的訊息傳送失敗,RocketMQ提供了一種優雅關閉Broker的方法,通過執行以下命令會清除Broker的寫許可權,過40s後,所有客戶端都會更新Broker路由資訊,此時再關閉Broker就不會發生髮送訊息失敗的情況,因為所有訊息都發往了其他 Broker。
# sh mqadmin wipeWritePerm -b brokerName -n namesrvAddr
- Master 與Slave的關係
RocketMQ的開源版本,Master宕機,Slave不能切換為Master,這裡的Slave不可寫,但可讀,類似於 Mysql 主備方式。