org.apache.rocketmq.client.exception.MQClientException: No route info of this topic
小编:管理员 765阅读 2022.08.03
笔者最近在使用rocketmq时,使用部署在docker中的rocketmq就会报“org.apache.rocketmq.client.exception.MQClientException: No route info of this topic”异常,win10本地启动同版本的rocketmq release库没有任何问题,搜索了许久仍然没有找到问题,关于这个问题,部分原因在笔者,笔者没有完全按照http://rocketmq.apache.org/docs/simple-example/里面的demo引入下面的rocketmq-client依赖,而是引入的rocketmq-spring-boot-starter这个依赖,示例代码如下:
@Test public void send() throws MQClientException, UnsupportedEncodingException, RemotingException, InterruptedException, MQBrokerException { //Instantiate with a producer group name. DefaultMQProducer producer = new DefaultMQProducer("my-group1"); //rocketmq nameserver地址 producer.setNamesrvAddr("172.21.52.27:9876"); producer.start(); Message msg = new Message("test" /* Topic */, "TagA" /* Tag */, ("Hello RocketMQ ").getBytes("utf-8") /* Message body */ ); //Call send message to deliver message to one of brokers. SendResult sendResult = producer.send(msg); System.out.printf("%s%n", sendResult); //Shut down once the producer instance is not longer in use. producer.shutdown(); }复制
经过跟踪发现标红部分的代码根本没有起作用,为什么没起作用呢,下面看下DefaultMQProducer的构造方法:
public DefaultMQProducer(String producerGroup, RPCHook rpcHook) { this.log = ClientLogger.getLog(); this.createTopicKey = "TBW102"; this.defaultTopicQueueNums = 4; this.sendMsgTimeout = 3000; this.compressMsgBodyOverHowmuch = 4096; this.retryTimesWhenSendFailed = 2; this.retryTimesWhenSendAsyncFailed = 2; this.retryAnotherBrokerWhenNotStoreOK = false; this.maxMessageSize = 4194304; this.traceDispatcher = null; this.producerGroup = producerGroup; //创建DefaultMQProducerImpl对象 this.defaultMQProducerImpl = new DefaultMQProducerImpl(this, rpcHook); } //发送消息 public SendResult send(Message msg) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { return this.defaultMQProducerImpl.send(msg); }复制
从send方法以及DefaultMQProducer的构造方法可以看出,引入rocketmq-spring-boot-starter引入后导致MQClientInstance实例被提前创建,提前创建使用的是application.yml文件中配置:
rocketmq: name-server: 127.0.0.1:9876 producer: group: my-group复制
该配置里面使用的就是127.0.0.1 而不是docker中部署的nameserver地址,虽然使用producer.setNamesrvAddr("172.21.52.27:9876")设置了rocketmq nameserver地址,但是其实是无效的,具体原因可以在MQClientManager类getAndCreateMQClientInstance方法查看,
public MQClientInstance getAndCreateMQClientInstance(ClientConfig clientConfig, RPCHook rpcHook) { String clientId = clientConfig.buildMQClientId(); MQClientInstance instance = (MQClientInstance)this.factoryTable.get(clientId); if (null == instance) { instance = new MQClientInstance(clientConfig.cloneClientConfig(), this.factoryIndexGenerator.getAndIncrement(), clientId, rpcHook); MQClientInstance prev = (MQClientInstance)this.factoryTable.putIfAbsent(clientId, instance); if (prev != null) { instance = prev; log.warn("Returned Previous MQClientInstance for clientId:[{}]", clientId); } else { log.info("Created new MQClientInstance for clientId:[{}]", clientId); } } return instance; }复制
由于引入rocketmq-spring-boot-starter导致getAndCreateMQClientInstance过早被创建,所以后续同一clientId不再创建MQClientInstance而使用最初创建的实例!
产生问题的原因在于最初application.proerties配置的是127.0.0.1:9876 虽然application.yml配对了地址,但是由于properties文件优先级比yaml文件高,导致一直使用的是127.0.0.1:9876这个错误地址,但是本地没有开启rocketmq服务,所以一直报"org.apache.rocketmq.client.exception.MQClientException: No route info of this topic"这个异常,搜索了很多最终都没有解决问题,最终单步调试解决了该问题。
PS:
1、是rocketmq的错误提示信息不够细,如果报connection exception之类的异常,也许早就解决了这个问题,但是却报出了很多场景都可能出现的”org.apache.rocketmq.client.exception.MQClientException: No route info of this topic“这个错误
2、引入rocketmq-spring-boot-starter以来时不要使用DefaultMQProducer发送信息
相关推荐
- 【RocketMQ系列】RocketMQ集群,RocketMQ-on-DLedger集群 本文RocketMQ系列第四篇,主要介绍RocketMQ集群及如何部署自动容灾切换的 RocketMQ-on-DLedger Group。RocketMQ集群搭建ROcketMQ集群搭建有以下几种方案:「单Master模式」「多Master模式」「多Master多Slave模式-异步复制」「多Master多Slave模式-同步双写」其…
- 3DMAX提示和技巧 本主题标识使用 Civil View 的一些重要提示和技巧。常规使用屏幕分辨率至少为 1280x1024 的 Civil View。低于此分辨率时,一些面板将占用过多屏幕空间。 将视口设置为线框显示以达到最佳性能。 要尽可能简化用户界面,请在单个视口中工作并关闭 3ds Max 命令面…