1. 程式人生 > >RocetMQ搭建攻略和問題解決之道

RocetMQ搭建攻略和問題解決之道

最近有在嘗試給專案加入訊息中介軟體服務,首先想到了鼎鼎大名的RocketMQ。RocketMQ是一款高效能的、分散式訊息中介軟體,由阿里開源。它提供了豐富的訊息拉取方式,能夠處理上億級的海量資料,甚至在阿里雙十上經受了超大的請求峰值,其商業可用性值得依賴和使用。 安裝方式比較簡單,就是在Rocket官網去下載對應版本的壓縮包。有兩種選擇,一種是binary版本,也就是編譯好的bin檔案壓縮包。還有一種是source版,就是需要被編譯的原始碼包。 我選擇使用編譯好的bin包,版本為最新的4.8.0。使用如下命令完成下載和解壓。順帶提一句本機安裝的Java版本是10.0.1,劃重點。 ``` cd ~/Downloads weget https://mirrors.bfsu.edu.cn/apache/rocketmq/4.8.0/rocketmq-all-4.8.0-bin-release.zip unzip rocketmq-all-4.8.0-bin-release.zip mv rocketmq-all-4.8.0-bin-release rocketmq ``` 然後需要啟動NameServer和Broker Server,首先是NameServer,命令如下所示: ``` cd ~/Downloads/rocketmq/bin ./mqnamesrv ``` 然後很有可能會遇到如下的報錯: > -Djava.ext.dirs=/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home/jre/lib/ext:/Users/tony/Downloads/rocketmq-all-4.8.0-source-release/distribution/bin/../lib:/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home/lib/ext is not supported. Use -classpath instead. Error: Could not create the Java Virtual Machine. 我根據這段報錯一番艱難地百度\bing\Google之後,發現沒有人遇到完全類似的問題,唯一接近的是Could not create the java Virtual Machine的報錯,我嘗試性進行了如下方法。 首先懷疑是因為我的Java版本太高了,導致有一些runserver.sh裡面的引數設定不能相容,因為namesrv會執行runserver.sh裡面的命令。按照騰訊雲上的原話是: 由於RocketMQ的啟動檔案都是按照JDK8配置的,而前面我特意配置的JDK版本是11,有很多命令引數不支援導致的,使用JDK8,正常啟動沒有問題的。 於是編輯bin/runserver.sh檔案,將下面的命令註釋掉: ``` # 註釋掉下面這行 #export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} # 修改成下面這行 export CLASSPATH=.:${BASE_DIR}/lib/*:${BASE_DIR}/conf:${CLASSPATH} ``` 然後還需要將JAVA_OPT的引數註釋一部分,它們的位置是在檔案內容最後,如下所示: ``` # 註釋下面這兩行 #JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib:${JAVA_HOME}/lib/ext" #JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" ``` 是不是看起來很眼熟?這就是前面我們遇到的報錯那段,據說是Java1.9之後使用-Djava.ext.dirs會有問題,我去RocketMQ的github上的issue討論看了一下,貌似官方團隊也沒有fix這個問題,2333。 儲存好這些修改,然後重新執行mqnamesrv即可,以後臺程式方式執行的命令如下: ``` nohup sh mqnamesrv & ``` 檢視執行的日誌的命令和其輸出如下: ``` tail -f ~/logs/rocketmqlogs/namesrv.log 2020-12-31 16:15:30 INFO main - tls.client.authServer = false 2020-12-31 16:15:30 INFO main - tls.client.trustCertPath = null 2020-12-31 16:15:30 INFO main - Using OpenSSL provider 2020-12-31 16:15:30 INFO main - SSLContext created for server 2020-12-31 16:15:30 INFO NettyEventExecutor - NettyEventExecutor service started 2020-12-31 16:15:30 INFO main - Try to start service thread:FileWatchService started:false lastThread:null 2020-12-31 16:15:30 INFO FileWatchService - FileWatchService service started 2020-12-31 16:15:30 INFO main - The Name Server boot success. serializeType=JSON 2020-12-31 16:16:30 INFO NSScheduledThread1 - -------------------------------------------------------- 2020-12-31 16:16:30 INFO NSScheduledThread1 - configTable SIZE: 0 ``` 說明NameServer已經正常啟動了。 第二步執行Broker Server,還是在bin目錄下執行: ./mqbroker 繼續收穫報錯,錯誤日誌輸出如下所示: ``` [0.002s][warning][gc] -Xloggc is deprecated. Will use -Xlog:gc:/Volumes/RAMDisk/rmq_broker_gc_%p_%t.log instead. Unrecognized VM option 'PrintGCDateStamps' Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. ``` 其本質還是無法建立Java虛擬機器,推測還是出在GC的一些引數在Java10.0上無法相容。檢視mqbroker腳本里面的內容,可以看到最後一行執行了如下命令: ``` sh ${ROCKETMQ_HOME}/bin/runbroker.sh org.apache.rocketmq.broker.BrokerStartup $@ ``` 說明執行了runbroker.sh指令碼,於是在runbroker.sh檔案中找到如下命令: ``` # 註釋掉下面這行 #export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} # 修改成下面這行 export CLASSPATH=.:${BASE_DIR}/lib/*:${BASE_DIR}/conf:${CLASSPATH} ``` 這段修改和mqnamesrv的類似,還有下面這段也需要調整: ``` JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g" JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0" JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_broker_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy" JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m" JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch" JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g" JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking" JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib:${JAVA_HOME}/lib/ext" #JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" ``` 註釋掉一些無效的命令,改後如下所示: ``` JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g" #JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0" #JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_broker_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy" #JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m" JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch" #JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g" JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking" JAVA_OPT="${JAVA_OPT} # -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib:${JAVA_HOME}/lib/ext" #JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" ``` 儲存上述修改,然後就可以正常啟動Broker Server了,執行下面命令: ``` nohup sh bin/mqbroker -n localhost:9876 & ``` 如果想最簡單的方式測試一下服務,那麼可以使用RocketMQ指令碼封裝好的工具,命令如下: ``` export NAMESRV_ADDR=localhost:9876 sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer ``` 可能遇到的報錯如下: ``` sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer -Djava.ext.dirs=bin/../lib:/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home/jre/lib/ext:/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home/lib/ext is not supported. Use -classpath instead. Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. ``` 還是在tools.sh做類似的修改,如下所示: ``` # 註釋下面這行 #export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} # 新增下面這行 export CLASSPATH=.:${BASE_DIR}/lib/*:${BASE_DIR}/conf:${CLASSPATH} .... JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m" # 註釋掉下面這行,JDK1.9後不再支援該引數 #JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${BASE_DIR}/lib:${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext" JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}" ``` 重新儲存後執行,如果看到如下輸出則說明成功了: ``` st, brokerName=Tony-Mac-Pro.local, queueId=3], queueOffset=247] SendResult [sendStatus=SEND_OK, msgId=7F000001203D1DE0ACA60ED7764803E0, offsetMsgId=AC101A0000002A9F0000000000031232, messageQueue=MessageQueue [topic=TopicTest, brokerName=Tony-Mac-Pro.local, queueId=0], queueOffset=248] SendResult [sendStatus=SEND_OK, msgId=7F000001203D1DE0ACA60ED7764A03E1, offsetMsgId=AC101A0000002A9F00000000000312FD, messageQueue=MessageQueue [topic=TopicTest, brokerName=Tony-Mac-Pro.local, queueId=1], queueOffset=248] SendResult [sendStatus=SEND_OK, msgId=7F000001203D1DE0ACA60ED7764C03E2, offsetMsgId=AC101A0000002A9F00000000000313C8, messageQueue=MessageQueue [topic=TopicTest, brokerName=Tony-Mac-Pro.local, queueId=2], queueOffset=248] SendResult [sendStatus=SEND_OK, msgId=7F000001203D1DE0ACA60ED7764E03E3, offsetMsgId=AC101A0000002A9F0000000000031493, messageQueue=MessageQueue [topic=TopicTest, brokerName=Tony-Mac-Pro.local, queueId=3], queueOffset=248] SendResult [sendStatus=SEND_OK, msgId=7F000001203D1DE0ACA60ED7764F03E4, offsetMsgId=AC101A0000002A9F000000000003155E, messageQueue=MessageQueue [topic=TopicTest, brokerName=Tony-Mac-Pro.local, queueId=0], queueOffset=249] SendResult [sendStatus=SEND_OK, msgId=7F000001203D1DE0ACA60ED7764F03E5, offsetMsgId=AC101A0000002A9F0000000000031629, messageQueue=MessageQueue [topic=TopicTest, brokerName=Tony-Mac-Pro.local, queueId=1], queueOffset=249] SendResult [sendStatus=SEND_OK, msgId=7F000001203D1DE0ACA60ED7765003E6, offsetMsgId=AC101A0000002A9F00000000000316F4, messageQueue=MessageQueue [topic=TopicTest, brokerName=Tony-Mac-Pro.local, queueId=2], queueOffset=249] SendResult [sendStatus=SEND_OK, msgId=7F000001203D1DE0ACA60ED7765103E7, offsetMsgId=AC101A0000002A9F00000000000317BF, messageQueue=MessageQueue [topic=TopicTest, brokerName=Tony-Mac-Pro.local, queueId=3], queueOffset=249] 21:10:01.562 [NettyClientSelector_1] INFO RocketmqRemoting - closeChannel: close the connection to remote address[172.16.26.0:10911] result: true 21:10:01.564 [NettyClientSelector_1] INFO RocketmqRemoting - closeChannel: close the connection to remote address[127.0.0.1:9876] result: true ``` 最終,我們和RocketMQ和解,完成了這次測試! 鳴謝下面的幫助,可以參考的資料如: [騰訊雲上的教程](https://cloud.tencent.com/developer/article/1639530) [官方quick start](http://rocketmq.apache.org/docs/quick