RocketMQ踩坑記


一、前言

現在的主流消息隊列基本都是kafka、RabbitMQ和RocketMQ,只有了解各自的優缺點才能在不同的場景選擇合適的MQ,對比圖如下:

MQ對比圖
MQ對比圖

本篇文章主要介紹我自己在跑官方demo時遇到的一些坑(基於4.3版本),建議先看看RocketMQ的理論知識。

Apache 上開源官方地址:https://rocketmq.apache.org/
GitHub 托管地址:https://github.com/apache/rocketmq
阿里官方的介紹文檔:http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/
Apache 官方提供的 4.3.0 版本的 “快速入門” 文檔:https://rocketmq.apache.org/docs/quick-start/

二、安裝

安裝過程可以參考官方的快速入門文檔,這時可能會遇見第一個坑。

坑一:啟動broker失敗,查看日志nohup.out 顯示內存不足

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000005c0000000, 8589934592, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 8589934592 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /usr/local/rocketmq-all-4.3.0/distribution/target/apache-rocketmq/hs_err_pid7209.lo

這是因為 apache-rocketmq/bin 目錄下啟動 nameserv 與 broker 的 runbroker.shrunserver.sh 文件中默認分配的內存太大,而系統實際內存卻太小導致啟動失敗。解決辦法就是修改runbroker.shrunserver.sh里的內存配置,調小一些即可。

runserver.sh
runserver.sh

runbroker.sh
runbroker.sh

三、運行官方示例

這時候在服務器啟動好namesrv和broker,你以為建個項目復制好代碼就萬事大吉了?

項目截圖
項目截圖

坑二:No route info of this topic
運行OnewayProducer的main方法控制台可能報如下錯誤:
org.apache.rocketmq.client.exception.MQClientException: No route info of this topic

網上的解決方案有好幾種,主要如下:

1.沒有創建topic

原因歸於我們沒有創建topic,要把啟動broker的命令改為nohup sh bin/mqbroker -n localhost:9876 autoCreateTopicEnable=true &

默認情況下 broker會自動創建話題,所以這個完全是沒用的。

2.防火牆問題

如果真是防火牆問題,那報錯信息一定連接失敗什么的,當時我也以為是這個問題但是發現防火牆已經關閉了。

3.pom文件的jar問題

pom文件上rocketmq-client的版本要與 /usr/local/rocketmq-all-4.3.2/distribution/target/apache-rocketmq/lib目錄下的jar包版本一致。當時項目pom.xml上的版本是4.3,RocketMQ上的是rocketmq-client-4.3.2.jar,后來將依賴改為4.3.2就好。

4.broker未啟動完畢

這是我發現的一種情況,broker啟動是需要時間的,日志顯示啟動成功后再運行代碼。

坑三:org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <172.19.0.1:10909> failed

再次運行OnewayProducer會發現錯誤又變了!

Exception in thread "main" org.apache.rocketmq.client.exception.MQClientException: Send [1] times, still failed, cost [4190]ms, Topic: TopicTest, BrokersSent: [bogon]
See http://rocketmq.apache.org/docs/faq/ for further details.
    at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendDefaultImpl(DefaultMQProducerImpl.java:610)
    at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendOneway(DefaultMQProducerImpl.java:905)
    at org.apache.rocketmq.client.producer.DefaultMQProducer.sendOneway(DefaultMQProducer.java:285)
    at cn.sp.simple.OnewayProducer.main(OnewayProducer.java:21)
Caused by: org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <172.19.0.1:10909> failed
    at org.apache.rocketmq.remoting.netty.NettyRemotingClient.invokeOneway(NettyRemotingClient.java:561)
    at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage(MQClientAPIImpl.java:324)
    at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage(MQClientAPIImpl.java:294)
    at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendKernelImpl(DefaultMQProducerImpl.java:785)
    at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendDefaultImpl(DefaultMQProducerImpl.java:529)
    ... 3 more

重點在於connect to <172.19.0.1:10909> failed這里的ip地址並不是我本地虛擬機的ip地址,我們需要手動設置broker的ip地址

#進入rocketmq根目錄
cd /usr/local/rocketmq-all-4.3.2/distribution/target/apache-rocketmq
#編寫配置文件,並寫好配置
echo "brokerIP1=10.2.x.x" > broker.properties
#啟動 mqnamesrv 
nohup sh bin/mqnamesrv &

#重點:mrbroker 啟動時通過 -c 加載配置文件
nohup sh bin/mqbroker -n localhost:9876 -c /usr/local/rocketmq-all-4.3.2/distribution/target/apache-rocketmq/broker.properties &

這時可以正常的生產消息和消費了,但是當我運行異步生產消息的AsyncProducer時又開始報錯了!

坑四:官方示例AsyncProducer代碼錯誤

錯誤信息截圖
錯誤信息截圖

問題的原因是主線程提前關閉,導致異步線程受到影響,所以可以用CountDownLatch來解決,修改后代碼如下:

public class AsyncProducer {

  public static void main(String[] args) throws Exception {
    //Instantiate with a producer group name.
    DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
    // Specify name server addresses.
    producer.setNamesrvAddr("192.168.75.132:9876");
    //Launch the instance.
    producer.start();
    producer.setRetryTimesWhenSendAsyncFailed(0);
    int messageCount  = 100;
 
    final CountDownLatch countDownLatch  = new CountDownLatch(messageCount);
    for (int i = 0; i < messageCount; i++) {
      final int index = i;
      //Create a message instance, specifying topic, tag and message body.
      Message msg = new Message("TopicTest",
          "TagA",
          "OrderID188",
          "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
      producer.send(msg, new SendCallback() {
        @Override
        public void onSuccess(SendResult sendResult) {
          countDownLatch.countDown();
          System.out.printf("%-10d OK %s %n", index,
              sendResult.getMsgId());
        }
        @Override
        public void onException(Throwable e) {
          countDownLatch.countDown();
          System.out.printf("%-10d Exception %s %n", index, e);
          e.printStackTrace();
        }
      });
    }
    countDownLatch.await();
    //Shut down once the producer instance is not longer in use.
    producer.shutdown();
  }
}

重新運行該類,發現問題終於解決了。

enter description here
enter description here

補充一下RocketMQ可視化控制台的搭建步驟

  1. 下載源代碼,github地址為:https://github.com/apache/rocketmq-externals
  2. 進入目錄rocketmq-console,運行命令 mvn clean package -DskipTests=true得到jar包文件rocketmq-console-ng-1.0.1.jar
  3. 上傳rocketmq-console-ng-1.0.1.jar,使用nohup命令啟動即可。
  4. 游覽器訪問http://ip:8080即可看到web管理界面,如下圖。

enter description here
enter description here

四、總結

原本以為就搭個環境跑個demo很快就能完成,沒想到遇到了這么多坑,不過也收獲很多。

參考資料:
https://blog.csdn.net/wangmx1993328/article/details/81536168
https://my.oschina.net/u/3476125/blog/897429
https://blog.csdn.net/jessDL/article/details/86646086


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM