背景
最近在学习RocketMQ,第一步就是安装部署并启动RocketMQ。使用最新版本的RocketMQ,版本为4.2.0,安装后启动相关服务。
启动nameServer:
nohup mqnamesrv &
由于broker和nameServer在同一台机器上,启动broker:
nohup mqbroker -n localhost:9876 &
接下来运行producer的demo,但是在运行demo的过程中出现了问题,异常堆栈如下:
org.apache.rocketmq.client.exception.MQClientException:
Send [3] times, still failed, cost [3004]ms,
Topic: MQ-MSG-TOPICS-TEST, BrokersSent:
[iZnqntg5t2znd7Z, iZnqntg5t2znd7Z, iZnqntg5t2znd7Z]
See http://rocketmq.apache.org/docs/faq/ for further details.
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.
sendDefaultImpl(DefaultMQProducerImpl.java:544)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.
send(DefaultMQProducerImpl.java:1069)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.
send(DefaultMQProducerImpl.java:1023)
at org.apache.rocketmq.client.producer.DefaultMQProducer.
send(DefaultMQProducer.java:214)
at core.RocketMQProducer.send(RocketMQProducer.java:44)
at core.RocketMQProducerTest.main(RocketMQProducerTest.java:20)
Caused by: org.apache.rocketmq.remoting.exception.RemotingConnectException:
connect to <172.18.46.234:10909> failed
at org.apache.rocketmq.remoting.netty.NettyRemotingClient.
invokeSync(NettyRemotingClient.java:388)
at org.apache.rocketmq.client.impl.MQClientAPIImpl.
sendMessageSync(MQClientAPIImpl.java:351)
at org.apache.rocketmq.client.impl.MQClientAPIImpl.
sendMessage(MQClientAPIImpl.java:335)
at org.apache.rocketmq.client.impl.MQClientAPIImpl.
sendMessage(MQClientAPIImpl.java:298)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.
sendKernelImpl(DefaultMQProducerImpl.java:696)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.
sendDefaultImpl(DefaultMQProducerImpl.java:463)
... 5 more
现将问题的排查及解决方法记录如下.
排查
遇到这个问题后,根据异常信息知道是无法连接到172.18.46.234:10909.那么这个地址是nameServer的还是broker的呢?
在demo中配置的nameServer地址是阿里云服务器的公网地址,而且端口号是默认的9876,因此172.18.46.234:10909是broker的地址,即producer尝试连接broker时失败.
后来发现172.18.46.234是我的阿里云服务器的内网地址,我们回忆下RocketMQ的工作流程:
启动nameServer
broker启动时使用-n localhost:9876指定nameServer,将自己的IP地址注册到nameServer
producer首先连接nameServer,获取可用的broker地址
producer根据从nameServer获取的broker地址,将信息发送给broker
因此错误的原因是broker将自己内网地址发送给了nameServer,producer从nameServer获取的是broker的内网IP地址,自然无法连接broker.
解决方案
由上可知,只要broker将自己的外网地址注册到nameServer即可,查阅资料发现,broker注册到nameServer的地址可以使用参数配置,参数为brokerIP1和brokerIP2(个人推测这两个IP应该一个是普通channel,一个是vip channel),但是如何在broker启动时设置这两个参数呢?
查看RocketMQ中org.apache.rocketmq.broker.BrokerStartup源码可知,broker启动选项如下:
短选项 | 长选项 | 是否必填 | 是否需要参数 | 参数是否可选 | 含义 |
---|---|---|---|---|---|
n | nameSrvAddr | 否 | 是 | 否 | Name server address list, eg: 192.168.0.1:9876;192.168.0.2:9876 |
c | configFile | 否 | 是 | 否 | Broker config properties file |
h | help | 否 | 否 | - | Print help |
p | printConfigItem | 否 | 否 | - vPrint all config item | |
m | printImportantConfig | 否 | 否 | - | Print important config item |
备注
若选项需要参数,则参数是否可选为否时表示该选项后必须跟一个参数
若选项无需参数,则参数是否可选无意义
由上可知,启动broker时共有5个选项,比较常用的是-n和-c,-n用于指定nameServer的IP地址及端口号,-c用于指定配置文件,同时nameServer的IP地址及端口号也可用nameSrvAddr在配置文件中设置,这样启动broker时就不用使用选项指定nameServer了.
RocketMQ在$ROCKETMQ_HOME/conf下提供了几个默认的配置文件,如2m-2s-async文件夹中提供了4个配置文件,分别是2个master和2个slave,且master和slave使用异步方式同步数据;而broker.conf提供了集群中只有一个master,无slave的配置文件,在配置文件中添加brokerIP1,brokerIP2,nameSrvAddr属性,内容如下:
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
# brokerIP1和brokerIP2默认获取本地ip地址,在云服务器上会获取内网ip地址,因此必须显式设置
brokerIP1=*.*.*.*
brokerIP2=*.*.*.*
# 将namesrvAddr设置在configfile中
namesrvAddr=localhost:9876
其中brokerIP1和brokerIP2修改为自己云服务器的外网地址.
启动broker(假设当前工作目录为$ROCKETMQ_HOME/bin):
nohup mqbroker -c ../conf/broker.conf &
1
再次运行demo,即可成功向broker发送消息.
总结
broker向nameServer注册的地址是brokerIP1,brokerIP2,
@ImportantField
private String brokerIP1 = RemotingUtil.getLocalAddress();
private String brokerIP2 = RemotingUtil.getLocalAddress();
在阿里云服务器上获取的是内网IP地址,因此producer从nameServer获取的broker地址是broker的内网IP地址,无法向broker发送消息.
可以通过-c指定broker启动时的配置文件,在配置文件中添加brokerIP1和brokerIP2属性,其值为阿里云服务器的外网IP地址,即可解决上述问题.
除此之外,RocketMQ还提供了-h,-p,-m用于打印帮助,打印配置项和打印重要配置项供用户参考.
还可将nameServer的地址通过nameSrvAddr属性写在配置文件中,这样启动时就无需通过-n设置nameServer地址.
参考
rocketmq官网quick-start
作者:pfjia
来源:CSDN
原文:https://blog.csdn.net/jpf254/article/details/80748021
版权声明:本文为博主原创文章,转载请附上博文链接!