前言
由于最近项目要升级消息中间件,因此对消息中间件进行了一些调研,看了一些东西之后首当其冲准备试试RocketMQ,因此先搭建个环境试用一下。
部署
部署的RocketMQ版本3.2.6,系统环境Centos6+jdk7
将压缩包alibaba-rocketmq-3.2.6.tar.gz上传到/usr/local并解压缩
tar -zxvf alibaba-rocketmq-3.2.6.tar.gz
解压得到alibaba-rocketmq文件夹,建立个rocketmq的软连接方便使用
ln -s alibaba-rocketmq rocketmq
创建存储路径
# mkdir /usr/local/rocketmq/store
# mkdir /usr/local/rocketmq/store/commit
# mkdir /usr/local/rocketmq/store/consum
# mkdir /usr/local/rocketmq/store/index
配置
接下来需要设置broker的配置文件,这也是最重要的一块,其实在/usr/local/rocketmq/conf下默认给了一些配置的demo,定位到该文件夹下
可以看到其中有2m-2s-async,2m-2s-sync和2m-noslave三个文件夹,每一个都代表一种集群模式,m和s分别代表主和从,async和sync是指主从之间数据复制的形式是异步还是同步,此处我们选择2m-2s-async方式进行搭建。
进入2m-2s-async文件夹后可以看到有4个配置文件,分别对应的就是2主2从的配置,根据搭建的服务的角色设置对应的配置文件即可,其他几个都可以忽略。由于demo中给的配置非常简单,这意味着很多配置项都采用了默认值,初学阶段为了了解尽可能多的配置项,特意从网上找了一个比较全的模板
#所属集群名字
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 对外服务的监听端口,10911为默认值
listenPort=10911
#表示Master监听Slave请求的端口,默认为服务端口+1
haListenPort=10912
#删除文件时间点,默认凌晨 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
其中brokerName、brokerId、brokerRole这几个参数是要重点关注的,因为broker的角色不同时配置是有差异的。而当==单台服务器上跑多个RocketMQ实例==时有一个点要特别注意,那就是listenPort和haListenPort的配置,大多数情况下haListenPort是默认不配的,因此当一个实例使用默认的listenPort=10911端口时,haListenPort会默认占用10912端口,因此需要再配置下一个RocketMQ实例时要避开上述两个端口。
接着新建一个存放日志的文件夹
# mkdir -p /usr/local/rocketmq/logs
批量修改conf下日志文件的配置,将配置中所有的${user.home}变量替换为/usr/local/rocketmq
cd /usr/local/rocketmq/conf && sed -i 's#${user.home}#/usr/local/rocketmq#g' *.xml
修改bin目录下的启动脚本参数runbroker.sh和runserver.sh
JAVA_OPT="${JAVA_OPT} -server ==-Xms1g -Xmx1g -Xmn512m== -XX:PermSize=128m -XX:MaxPermSize=320m"
服务启动
服务启动包括两部分,NameServer的启动和BrokerServer的启动,其中NameServer类似于注册中心的角色,而BrokerServer才是真正处理消息的服务器。
启动NameServer服务
# cd /usr/local/rocketmq/bin
# nohup sh mqnamesrv &
报了如下错误
nohup: ignoring input and appending output to `nohup.out'
根据提示去nohup.out文件中查找异常日志,有如下内容
ERROR: Please set the JAVA_HOME variable in your environment, We need java(x64)! !!
这才发现这台服务器上压根儿都没有装jdk。。。以为开发环境的服务器jdk肯定安装了,看来还是大意了。然而安装完jdk7之后,依然报错
java.lang.ExceptionInInitializerError
at com.alibaba.rocketmq.namesrv.NamesrvStartup.main0(NamesrvStartup.java:125)
at com.alibaba.rocketmq.namesrv.NamesrvStartup.main(NamesrvStartup.java:70)
Caused by: java.lang.RuntimeException: InetAddress java.net.InetAddress.getLocalHost() throws UnknownHostException
See https://github.com/alibaba/RocketMQ/issues/64 for further details.
at com.alibaba.rocketmq.common.MixAll.localhost(MixAll.java:458)
at com.alibaba.rocketmq.common.MixAll.<clinit>(MixAll.java:82)
... 2 more
Caused by: java.net.UnknownHostException: dev01.homeopen.rcs: dev01.homeopen.rcs: Name or service not known
at java.net.InetAddress.getLocalHost(InetAddress.java:1475)
at com.alibaba.rocketmq.common.MixAll.localhost(MixAll.java:454)
... 3 more
Caused by: java.net.UnknownHostException: dev01.homeopen.rcs: Name or service not known
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$1.lookupAllHostAddr(InetAddress.java:901)
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1295)
at java.net.InetAddress.getLocalHost(InetAddress.java:1471)
... 4 more
这个问题就比较常见了,系统配置了hostname为dev01.homeopen.rcs,但在/etc/hosts中没有配置对应的名称,需要增加上对应的名称,修改完之后成功启动。
启动BrokerServer
cd /usr/local/rocketmq/bin
# nohup sh mqbroker -c /usr/local/rocketmq/conf/2m-2s-async/broker-a.properties >/dev/null 2>&1 &
启动完成之后可以通过日志查看NameServer和BrokerServer的启动情况,日志路径如下
# tail -f -n 500 /usr/local/rocketmq/logs/rocketmqlogs/broker.log
# tail -f -n 500 /usr/local/rocketmq/logs/rocketmqlogs/namesrv.log
服务管理
如果需要查询BrokerServer集群的情况,可以使用如下命令查看
sh mqadmin clusterList -n "172.28.19.70:9876;172.28.19.97:9876"
但更建议是使用可视化的界面来进行监控,这里使用的是rocketmq-console-ng这个工具,该页面支持中文,可以在github上的rocketmq-externals项目下找到。由于是基于Spring-boot开发的,因此可以不需要容器直接启动,官网给出启动方式如下,启动后默认监控的NameSvrAddrList为127.0.0.1:9876,也可在OPS页中进行修改。
mvn clean package -Dmaven.test.skip=true
java -jar target/rocketmq-console-ng-1.0.0.jar
顺带补充一下,服务停止的命令如下:
# cd /usr/local/rocketmq/bin
# sh mqshutdown broker
# sh mqshutdown namesrv
补充
[root@dev08 bin]# netstat -anp | grep 10911
tcp 0 0 :::10911 :::* LISTEN 6598/java
tcp 0 0 ::ffff:172.28.19.97:52332 ::ffff:172.28.19.70:10911 TIME_WAIT -
tcp 0 0 ::ffff:172.28.19.97:52326 ::ffff:172.28.19.70:10911 TIME_WAIT -
[root@dev08 bin]# netstat -anp | grep 10911
tcp 0 0 :::10911 :::* LISTEN 6598/java
tcp 0 0 ::ffff:172.28.19.97:52458 ::ffff:172.28.19.70:10911 TIME_WAIT -
tcp 0 0 ::ffff:172.28.19.97:59946 ::ffff:172.28.19.97:10911 TIME_WAIT -
tcp 0 0 ::ffff:172.28.19.97:10911 ::ffff:172.28.19.70:55314 ESTABLISHED 6598/java
tcp 0 0 ::ffff:172.28.19.97:52394 ::ffff:172.28.19.70:10911 ESTABLISHED 6829/java
搭建的时候遇到一个比较奇怪的问题,当同一服务器的两个实例listenPort分别设置10911和10913时,10913的服务启动以后会对10911的服务有影响,启动前后10911端口变化如上图,看到某篇blog中有提到,两个实例的端口相差2的时候存在问题,目前怀疑有可能是这个情况造成的影响,因为同时起10911和20911的两个实例不存在异常情况。