当前位置:   article > 正文

RocketMQ-记RocketMQ启动后producer无法连接到broker的错误及解决方案_org.apache.rocketmq.client.exception.mqclientexcep

org.apache.rocketmq.client.exception.mqclientexception: send [3] times, stil

背景
最近在学习RocketMQ,第一步就是安装部署并启动RocketMQ.使用最新版本的RocketMQ,版本为4.2.0,安装后启动相关服务. 
启动nameServer:

nohup mqnamesrv &
1
由于broker和nameServer在同一台机器上,启动broker:

nohup mqbroker -n localhost:9876 &
1
接下来运行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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
现将问题的排查及解决方法记录如下.

排查
遇到这个问题后,根据异常信息知道是无法连接到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    否    否    -    Print 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     
1
2
3
4
5
6
7
8
9
10
11
12
其中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();
1
2
3
在阿里云服务器上获取的是内网IP地址,因此producer从nameServer获取的broker地址是broker的内网IP地址,无法向broker发送消息. 
可以通过-c指定broker启动时的配置文件,在配置文件中添加brokerIP1和brokerIP2属性,其值为阿里云服务器的外网IP地址,即可解决上述问题. 
除此之外,RocketMQ还提供了-h,-p,-m用于打印帮助,打印配置项和打印重要配置项供用户参考. 
还可将nameServer的地址通过nameSrvAddr属性写在配置文件中,这样启动时就无需通过-n设置nameServer地址.
--------------------- 
作者:pfjia 
来源:CSDN 
原文:https://blog.csdn.net/jpf254/article/details/80748021 
版权声明:本文为博主原创文章,转载请附上博文链接!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/256981
推荐阅读
相关标签
  

闽ICP备14008679号