RocketMQ搭建步驟
開發環境
- 64位 centos7(虛擬機,1G內存)
- 64位 jdk1.8
- maven 3.5.0
- Git
- tomcat(用於啓動rocketmq-console)
- rocketmq 3.2.6(最好選擇maven倉庫中已有的版本,保持客戶端依賴的jar包和服務器版本一致)
- rocketmq-console
環境變量配置
vi /etc/profile 打開文件配置如下:
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk
JRE_HOME=$JAVA_HOME/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
M2_HOME=/usr/maven/
ROCKETMQ_HOME=/usr/rocketmq
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$M2_HOME/bin:$ROCKETMQ_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH M2_HOME ROCKETMQ_HOME PATH
export NAMESRV_ADDR=127.0.0.1:9876
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
source /etc/profile 使配置文件立即生效
防火牆配置
宿主機需要遠程訪問虛擬機的rocketmq服務和web服務,需要開放相關的端口號,簡單粗暴的方式是直接關閉防火牆
service iptables stop 關閉防火牆
service iptables status 查看防火牆的狀態
service iptables start 啓動防火牆
- 1
- 2
- 3
- 4
或者爲了安全,只開放特定的端口號,如8080、9876、10911等等,此處不再贅述。
安裝、啓動RocketMQ
1.下載和安裝
cd /usr
wget https://github.com/alibaba/RocketMQ/releases/download/v3.2.6/alibaba-rocketmq-3.2.6.tar.gz
tar -zxvf alibaba-rocketmq-3.2.6.tar.gz
mv alibaba-rocketmq-3.2.6 rocketmq
- 1
- 2
- 3
- 4
- 5
cd rocketmq/bin 進入rocketmq核心命令文件目錄
2.設置可執行權限
chmod +x mqadmin mqbroker mqfiltersrv mqshutdown mqnamesrv
- 1
- 2
3.修改jvm參數
vim修改runserver.sh和runbroker.sh的jvm參數如下(根據虛擬機內存大小設置,超出內存大小可能會報錯):
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m -XX:PermSize=128m -XX:MaxPermSize=320m"
- 1
- 2
- 3
4.啓動nameserver
nohup sh mqnamesrv &
- 1
- 2
5.配置broker
(1)創建broker配置文件
mkdir ../conf/me-2m-2s-async/
sh mqbroker -m >../conf/me-2m-2s-async/broker.p
- 1
- 2
- 3
(2)修改brokerIP
vi ../conf/me-2m-2s-async/broker.p
brokerIP1=192.168.x.x 顯示指定爲虛擬機的外網IP,不要用localhost和127.0.0.1,因爲遠程主機會根據brokerIP1指定的地址去訪問broker
- 1
- 2
- 3
6.啓動broker
nohup sh mqbroker -n localhost:9876 -c ../conf/me-2m-2s-async/broker.p &
- 1
- 2
7.檢查nameserver和broker是否啓動成功
執行jps,輸出以下進程表示啓動成功
8464 NamesrvStartup
8618 BrokerStartup
- 1
- 2
- 3
或者,查看nuhup.out日誌文件,有如下信息表示啓動成功
The Name Server boot success.
The broker[localhost.localdomain, 192.168.x.x:10911] boot success. and name server is localhost:9876
- 1
- 2
- 3
或者,啓動rocketmq自帶的Producer和Consumer程序,若可正常發送和消費消息,則表示服務啓動成功
bash tools.sh com.alibaba.rocketmq.example.quickstart.Producer #生產者
bash tools.sh com.alibaba.rocketmq.example.quickstart.Consumer #消費者
- 1
- 2
- 3
8.關閉nameserver和broker的方法
sh mqshutdown broker
sh mqshutdown namesrv
- 1
- 2
- 3
安裝、啓動rocketmq-console
wget https://github.com/duomu/rocketmq-console/raw/master/rocketmq-console.war 下載
將rocketmq-console.war放在/usr/tomcat/webapps目錄下
sh /usr/tomcat/bin/startup.sh 啓動tomcat
- 1
- 2
- 3
- 4
虛擬機本地訪問http://localhost:8080/rocketmq-console,顯示如下頁面表示啓動成功
宿主機遠程訪問http://192.168.x.x:8080/rocketmq-console,若無法訪問,請檢查防火牆是否關閉或者是否開放了8080端口號。
編寫測試程序
在宿主機(windows)上編寫如下測試程序:
依賴配置
//此處只列出mq相關的依賴
<dependency>
<groupId>com.alibaba.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>3.2.6</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
創建生產者
package com.fuscent.infoquery.practice.rocketmq;
import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.common.message.Message;
import org.apache.log4j.Logger;
/**
* @author:duomu
* @date:2017/8/4 18:09
*/
public class MqProducer {
private static Logger logger = Logger.getLogger(MqProducer.class);
public static void main(String[] args) {
DefaultMQProducer producer = new DefaultMQProducer("Producer");
producer.setNamesrvAddr("192.168.229.132:9876");
try {
producer.start();
logger.info("producer啓動成功");
for (int i = 0; i < 5; i++) {
Message msg = new Message("TopicA", "tagA", "OrderID188", "Hello world".getBytes());
SendResult result = producer.send(msg);
logger.info("id:" + result.getMsgId() + " result:" + result.getSendStatus());
}
} catch (Exception e) {
logger.error("發送消息失敗,Exception error:" + e);
} finally {
producer.shutdown();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
創建消費者
package com.fuscent.infoquery.practice.rocketmq;
import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere;
import com.alibaba.rocketmq.common.message.Message;
import com.alibaba.rocketmq.common.message.MessageExt;
import org.apache.log4j.Logger;
import java.util.List;
/**
* @author:duomu
* @date:2017/8/4 18:09
*/
public class MqConsumer {
private static Logger logger = Logger.getLogger(MqConsumer.class);
public static void main(String[] args) {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("PushConsumer_yll");
consumer.setNamesrvAddr("192.168.229.132:9876");
try {
consumer.subscribe("TopicA", "tagA||tagB");//可訂閱多個tag,但是一個消息只能有一個tag
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
Message msg = list.get(0);
logger.info(msg.toString());
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
logger.info("consumer啓動成功");
} catch (MQClientException e) {
logger.error("消費者訂閱消息失敗,error:" + e);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
測試生成者和消費者
啓動生成者
啓動消費者
總結
前人栽樹,後人乘涼,在baidu+google了n篇文章後,終於把rocketmq搭建成功了,雖然只是單機配置,但是把該踩的坑都踩了,集羣搭建應該只是多配幾臺服務而已,後續再研究啦~~~
坑1
在github上下載了最新的rocketmq4.1.0,後來發現maven中央倉庫還沒有4.1.0的rocketmq-client依賴包,後來下載了3.5.8,也沒有調成功,索性下載一個比較早期的版本,選了3.2.6,我們公司用的3.2.4,比我們公司的早一點點應該不會太差。。。
坑2
nameserver和broker啓動成功,宿主機上的生產者發送消息失敗,報如下錯誤,且指向錯誤碼33/44/50:
com.alibaba.rocketmq.client.exception.MQClientException:Send [1] times, still failed, cost [75]ms,...
- 1
- 2
出現這個問題首先要查看虛擬機本地的producer是否可以正常發送消息,如果本地收發消息正常,那麼一定遠程訪問的過程中出了問題,可能是端口號沒開放,也可能是IP地址映射有問題。
對於端口號,我已經確定了n遍,防火牆是關閉的,最初還沒有考慮到IP地址的問題,所以百思不得其解,從阿里官方渠道獲取了錯誤33/44/50的解決方案,試了一下也沒用,把rocketmq3.2.6源碼裏面的Producer跑了一下也是報那個錯誤,錯誤44的說明裏寫着可能是producer沒有正確連接到NameServer,我知道沒有連接成功,可是防火牆我都關閉了還能有什麼原因呢。
搗鼓了大半天,就卡在這個問題上了,我想我一定是漏掉了什麼,反反覆覆看38/44/50的錯誤說明,直到看到錯誤50說明裏面的這一句話:
然後我注意到下面這個嵌套錯誤,debug了一下,也沒看出什麼,當時我還以爲這個ip是虛擬機的局域網ip
接着就baidu+google,偶然google出一篇思路別具一格的文章,說rocketmq自動識別網絡出錯,要把其他網絡關掉,我之前學習docker的時候的確在虛擬機上配了docker的網絡。
然後就嘗試關掉docker的網絡(172.17.0.1),可是關掉了還是照樣報上面的錯誤啊。。。
真的沒有辦法了,今天早晨來了突然想到,能夠訪問外網ip不能訪問局域網ip,ping一下看看吧,果然局域網ip ping不通,由於對網絡、虛擬機瞭解的不深,我就去求教網絡童鞋了,問宿主機怎麼能夠訪問虛擬機的局域網ip(我用的NAT模式),網絡童鞋說你用橋接模式吧,當時心中暗喜,心想吼吼我的大難題就要這麼簡單的解決了,網絡童鞋走後,我就試了一下,麻蛋爲什麼用橋接模式分了新的ip(172.16.2.129),還是報上面那個172.17.0.1的錯誤。。
第一次搭rocketmq,想盡快調通,基本上都是用的默認配置,而且默認配置一般不會有問題啊,自己寫配置才容易出錯,然鵝萬能的百度告訴我我之前先入爲主的觀念是錯的,我想這應該是終極解決方案了吧。。
原來broker自動尋的地址是172.17.0.1,而且深深的刻在了默認配置文件裏,雖然我關掉了這個網絡,配置文件裏還是這個地址,然後我重新寫了個配置文件,強制指定broker所在的機器ip爲192.168.x.x,重啓服務,大功告成!
和局域網ip能否ping通無關,我把網絡連接改回了NAT模式,感謝網絡童鞋的幫忙,我要好好補一下網絡和虛擬機的知識了。。。
參考資料
附上最有價值的幾個~~
http://rocketmq.apache.org/docs/quick-start/ 官方資料,搭建mq之前最好把User Guide都看一遍
https://firsh.me/2017/07/19/rocketmq-p-c/
https://my.oschina.net/xcafe/blog/814135 坑2的終極解決方案
http://www.cnblogs.com/badboyf/p/6611774.html