一、rocketmq簡介
Apache RocketMQ是一個分佈式消息傳遞和流媒體平臺,具有低延遲,高性能和可靠性,萬億級容量和靈活的可擴展性。RocketMQ的前身是MetaQ,是阿里根據kafka的設計理念 ,使用Java語言開發的一個消息隊列,所以MetaQ和kafka有許多類似的地方。而rocketMQ在MetaQ的基礎上,摒棄了zookeeper的使用,轉而開發了namesrv來管理節點,這個變化讓rocketmq更加高可用,易擴展,但也限制了rocketmq不能自主選舉master,角色配置必需在配置文件中指定。
對於一個簡單的消息隊列部署,主要包括以下四個部分:
1、namesrv:代替zookeeper做節點管理
2、broker:進行消息接收,存儲,同步,發送,是消息隊列的核心
3、producer:生產者,發送消息到broker
4、consumer:消費者,從broker中接收消息
二、rocketmq安裝和配置
首先需要確保本地可以訪問Linux服務器,且Linux服務器不能設置nat,其內外網的IP需要一致纔行,否則本地無法與namesrv以及broker建立連接。雲服務器可能存在內外網IP不一致的問題,所以建議使用本地虛擬機,或者直接參考第六步建立本地調試環境,直接在本地運行。
安裝步驟:
從http://rocketmq.apache.org/release_notes/release-notes-4.3.2下載rocketmq4.3.2版本,也可以直接從git上下載https://github.com/apache/rocketmq/releases。Apache官網上有打包好了的壓縮包,也有源代碼包,而git上只有源碼包。
這裏主要介紹下載源碼包,自己編譯的流程。
先下載到本地後,再上傳到Linux服務器上(或者直接使用wget命令下載wget http://mirrors.tuna.tsinghua.edu.cn/apache/rocketmq/4.3.2/rocketmq-all-4.3.2-source-release.zip),並使用unzip rocketmq-all-4.3.2-source-release.zip命令解壓。然後進到解壓出來的目錄下,執行mvn -Prelease-all -DskipTests clean install -U,執行這一步需要提前安裝好Java環境和maven環境,這裏對jdk和maven環境安裝作簡單說明。
下載1.8版本以上的jdk,3.2版本以上的maven,解壓並配置環境變量,vim /etc/profile,在文件最後添加,這裏的具體路徑根據情況做修改。
export JAVA_HOME=/local/jdk1.8.0_191
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export MAVEN_HOME=/local/apache-maven-3.2.5
export PATH=$MAVEN_HOME/bin:$PATH
添加完成後執行source /etc/profile,之後執行java -version和mvn -version檢查環境是否安裝成功。
安裝完成後繼續執行打包命令,看到如下的結果說明打包成功。
在打包完成後,進到distribution/target/apache-rocketmq/bin/目錄下,使用vim修改啓動腳本,執行vim runserver.sh,主要修改如下配置:
主要是因爲默認的內存申請過大,擔心啓動時因內存不夠而無法啓動。修改成如下:
同樣修改vim runbroker.sh文件,修改爲如下配置。
在當前目錄下執行命令:
touch ~/logs/rocketmqlogs/namesrv.log創建日誌文件
nohup ./mqnamesrv & tail -f ~/logs/rocketmqlogs/namesrv.log啓動namesrv。
這時因爲需要打印日誌,無法再輸入命令,可以新開一個窗口,來啓動broker。在新窗口執行命令:
touch ~/logs/rocketmqlogs/broker.log
nohup ./mqbroker -n localhost:9876 & tail -f ~/logs/rocketmqlogs/broker.log來啓動broker。
關閉namesrv和broker命令分別爲
./mqshutdown namesrv
./mqshutdown broker
三、示例代碼
這時候的rocketmq已經可以使用了,可以通過Apache提供的示例程序,來使用rocketmq。
創建一個maven項目,引入如下依賴:
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.3.2</version>
</dependency>
同步發送示例代碼
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
/**
* 同步發送
*/
public class SyncProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new
DefaultMQProducer("ProducerGroup1");
//設置namesrv
producer.setNamesrvAddr("localhost:9876");
//啓動producer服務
producer.start();
try {
for (int i = 0; i < 1000; i++) {
//指定topic,指定tag,之後可以通過tag來篩選消息
Message msg = new Message("TopicTest" /* Topic */,
"TagA" /* Tag */,
("Hello RocketMQ" +
i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
);
//發送消息
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
Thread.sleep(2000);
}
}catch (Exception e){
System.out.println(e.getMessage());
}
producer.shutdown();
}
}
消費示例代碼
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import java.io.IOException;
import java.util.List;
public class Consumer {
public static void main(String[] args) throws InterruptedException, MQClientException, IOException {
//使用push監聽的方式來接收消息
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroup1");
//設置namesrv
consumer.setNamesrvAddr("localhost:9876");
//設置訂閱的topic
consumer.subscribe("TopicTest", "*");
//設置監聽器
consumer.registerMessageListener(new MessageListenerConcurrently() {
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
for(MessageExt msg : msgs){
System.out.println(new String(msg.getBody()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
System.out.printf("Consumer Started.%n");
}
}
發送端在控制檯打印:
消費端在控制檯打印:
四、添加broker配置
雖然上述安裝後rocketmq已經可以使用,但爲了個性化定製或者爲了主從配置,我們需要額外添加broker的配置文件。
broker配置文件在任意目錄下創建,我在/usr/local/rocketmq/conf中創建了配置文件broker-master.properties(將其中的ip換成你自己的Linux服務器ip):
#所屬集羣名字
brokerClusterName=rocketmq-cluster
#broker名字,master和slave的brokerName必須一致
brokerName=broker-master
#0 表示 Master,>0 表示 Slave
brokerId=0
#nameServer地址,分號分割。(配置slave後,需要在這添加slave的ip)
namesrvAddr=ip1:9876;ip2:9876
#指定master地址
#haMasterAddress=ip:10912
# 在發送消息時,自動創建服務器不存在的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
#讓broker只有在topic發生變化時纔想namesrv註冊
#forceRegister=false
#啓動並設置filterServer數量
#filterServerNums=1
#啓用broker的SQL92過濾
#enablePropertyFilter=true
之後broker啓動時使用-c,來指定具體的配置文件,nohup ./mqbroker -c /usr/local/rocketmq/conf/broker-master.properties & tail -f ~/logs/rocketmqlogs/broker.log
五、主從同步配置
構造一個最簡單的主從同步結構,單master單slave的情況。
在完成前四步後,我們其實已經有一個角色爲master的broker,之後需要在一個新的Linux服務器上啓動一個slave節點。主要是broker的配置不同。
#所屬集羣名字
brokerClusterName=rocketmq-cluster
#broker名字,master和slave的brokerName必須一致
brokerName=broker-master
#0 表示 Master,>0 表示 Slave
brokerId=1
#nameServer地址,分號分割,ip1是master的ip,ip2是slave的ip。
namesrvAddr=ip1:9876;ip2:9876
#指定master地址
#haMasterAddress=ip:10912
# 在發送消息時,自動創建服務器不存在的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=SLAVE
#刷盤方式
#- ASYNC_FLUSH 異步刷盤
#- SYNC_FLUSH 同步刷盤
flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false
#發消息線程池數量
sendMessageThreadPoolNums=128
#拉消息線程池數量
pullMessageThreadPoolNums=128
#讓broker只有在topic發生變化時纔想namesrv註冊
#forceRegister=false
#啓動並設置filterServer數量
#filterServerNums=1
#啓用broker的SQL92過濾
#enablePropertyFilter=true
啓動順序:先啓動master的namesrv,再啓動slave的namesrv,然後啓動master的broker,再啓動slave的broker。這個啓動順序不是必須的,即使由於順序不對導致broker向namesrv註冊失敗,在新的心跳後broker仍可以向master註冊。
六、構建調試環境
Windows系統下的調試
這裏基於idea編輯器,進行rocketmq調試。
從git上下載代碼到本地,也可以直接clone到idea中。
打開rocketmq項目,等待依賴下載完成。
先添加一個環境變量ROCKETMQ_HOME,值是項目目錄,例如E:\rocketmq-all-4.3.2-source-release\rocketmq-all-4.3.2。
之後在idea中選擇Run->EditConfiguration,選擇新窗口左上角的+號,添加Application。
添加broker的配置如下:
其中VM options爲:
-server
-Xms1g
-Xmx1g
-Xmn512m
-XX:+UseG1GC
-XX:G1HeapRegionSize=16m
-XX:G1ReservePercent=25
-XX:InitiatingHeapOccupancyPercent=30
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:SurvivorRatio=8
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintAdaptiveSizePolicy
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=30m
-XX:-OmitStackTraceInFastThrow
-XX:+AlwaysPreTouch
-XX:MaxDirectMemorySize=15g
-XX:-UseLargePages
-XX:-UseBiasedLocking
-verbose:gc
-Xloggc:D:\mq_gc1.log
Program arguments的配置是broker配置文件路徑。
之後再添加namesrv的配置如下:
其中VM options爲:
-server
-Xms1g
-Xmx1g
-Xmn512m
-XX:+UseG1GC
-XX:G1HeapRegionSize=16m
-XX:G1ReservePercent=25
-XX:InitiatingHeapOccupancyPercent=30
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:SurvivorRatio=8
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintAdaptiveSizePolicy
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=30m
-XX:-OmitStackTraceInFastThrow
-XX:+AlwaysPreTouch
-XX:MaxDirectMemorySize=15g
-XX:-UseLargePages
-XX:-UseBiasedLocking
-verbose:gc
-Xloggc:D:\mq_gc2.log
之後就可以在idea運行namesrv和broker。
如果需要調試mqadmin命令,則添加mqadmin。配置如下:
其中VM options爲:
-server
-Xms512m
-Xmx512m
-Xmn128m
-XX:PermSize=128m
-XX:MaxPermSize=128m
另外Program arguments中的就是你需要調試的mqadmin命令。
Linux系統下的調試
rocketmq也可以在Linux下調試,但個人覺得不是很方便。
在Linux系統下,編輯distribution/target/apache-rocketmq/bin/目錄下的runbroker.sh和runserver.sh,將這行的註釋去掉。
之後就可以使用jdb來調試namesrv和broker。