【RocketMQ】客户端报大量warn日志:No topic route info in name server for the topic:RMQ_SYS_TRACE_TOPIC、TBW102

目录

背景

问题排查

问题发现

问题分析

问题解决

解决方案

建议

总结


背景

业务团队使用的RocketMQ集群是我们中间件组搭建的,使用的客户端是微服务组基于原生的RocketMQ客户端封装的xcloud-rocketmq

业务团队在项目上线之后,反馈线上程序一直报错:

问题排查

1、看到业务团队这个表述,让我理解为线上集群存在问题,业务方topic在console创建成功了,但是发送消息时失败了,为了确保线上集群没问题,我先创建了一个测试的topic,写一个Java客户端进行发送消息,发现一切正常;

2、怀疑是客户端的问题,因为我使用的是原生的生产者,业务方使用的是微服务组封装的xcloud客户端,于是我使用了和业务方相同的客户端,测试结果仍然为正常,也没有报任何警告日志。

所以,用排除归纳法,能确定RocketMQ服务端和客户端都是正常的,不一样的是和业务方的使用方式、配置等。

问题发现

经过交流,发现业务方配置了RocketMQ客户端的日志,将RocketMQ客户端的日志也输出到了业务日志中,导致ELK采集到的业务日志一直打印RocketMQ客户端的异常信息,也就是说这个一直重复打印的日志,是一个警告日志,是RocketMQ客户端原生的日志。

<logger name="RocketmqClient" level="INFO" additivity="false">
  <appender-ref ref="INFO_FILE" />
</logger>

查看了源码,发现RocketMQ客户端确实会默默将日志打印到一个目录:

我查看了一下本机的~/logs/rocketmqlogs目录,确实有日志文件

看到了完整的异常日志信息之后,发现一个重要的信息:No topic route info in name server for the topic:RMQ_SYS_TRACE_TOPIC

RMQ_SYS_TRACE_TOPIC:这个topic是broker开启消息跟踪之后,系统自动创建的,但是我没有开启呀,按理说是不应该有这个topic的异常信息的;

TBW102:这个topic是Broker启动时,当autoCreateTopicEnable的配置为true时,会自动创建该默认topic,当生产者发送消息的topic没有创建时,会先路由到这个默认的topic,然后再继承该topic的配置,创建新的topic,但是我也没有开启自动创建topic;

所以,按照日志的分析来看,问题总结如下:

客户端会定时更新topic的路由信息,以保证客户端生产消费的正确性,此时服务端发现客户端请求了一个未知的topic:RMQ_SYS_TRACE_TOPIC,这个topic通过console上查找确认了,查无此topic,按照RocketMQ路由不到topic的逻辑,此时TBW102就出现了,由于没有开启自动创建topic,TBW102也不存在,这就导致了这个死循环,那么问题来了:为什么服务端没有RMQ_SYS_TRACE_TOPIC这个topic,但是客户端会报这个异常?

问题分析

带着疑问,来看追踪报错信息的源头,发现客户端更新topic列表的时候,不是直接从服务端获取topic列表信息,而是先查询所有的Consumer和Producer集合,再通过Consumer和Producer来获取所关联的topic,代码如下:

为什么会这么做,不像Kafka一样直接获取topic列表呢?猜想是Kafka用zk来存储元数据信息,能保证数据的强一致性,而RocketMQ无法保证,只能以客户端自己缓存的Consumer和Producer作为依据,来查所路由的topic信息。

为什么服务端没有RMQ_SYS_TRACE_TOPIC这个topic,但是客户端会报这个异常?

猜测:

1、有系统或用户的Consumer或Producer,关联到了RMQ_SYS_TRACE_TOPIC这个topic;

2、用户开启了消息追踪,设置了消息追踪的参数为true,从而导致客户端获取到的topic列表包含了这个topic,而服务端没有,就一直循环报错。

问题解决

解决方案

首先看官方的issues,也有人提出这个问题:

https://github.com/apache/rocketmq/issues/2938

官方的解释是:RocketMQ在4.4.0之后,支持消息追踪,如果客户端设置了消息追踪为true,需要在broker的配置文件中设置tracetopicEnable=true

这也符合我的猜想,应该是有客户端在构造Producer时,将tracetopicEnable参数传了true,所以需要传false或不传,或者将服务端配置修改为支持消息追踪。

public class Producer {
    public static void main(String[] args) throws MQClientException, InterruptedException {
​
        DefaultMQProducer producer = new DefaultMQProducer("zhurunhua", false);
        producer.setNamesrvAddr("172.20.10.42:9976;172.20.10.43:9976");
        producer.start();
        long l = System.currentTimeMillis();
        try {
            Message msg = new Message("test_topic",
                    "TagA",
                    "OrderID188",
                    "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
            SendResult sendResult = producer.send(msg);
            System.out.printf("cost:%s-->%s%n", (System.currentTimeMillis() - l), sendResult);
        } catch (Exception e) {
            log.error("", e);
        }
        producer.shutdown();
    }
}

但是查看的业务方的代码,并没有将消息追踪设置为true

@Component
@Slf4j
public class MqComp {
    @Resource
    private RocketMQTemplate rocketMqTemplate;
​
    public SendResult syncSendOrderly(String destination, Message<?> message, String hashKey) {
        return rocketMqTemplate.syncSendOrderly(destination, message, hashKey);
    }
​
    public void send(String destination, Message<?> message) {
        rocketMqTemplate.send(destination, message);
    }
​
    public void asyncSend(String destination, Message<?> message, SendCallback sendCallback, long timeout) {
        rocketMqTemplate.asyncSend(destination, message, sendCallback, timeout);
    }
}

于是我猜测,微服务组封装的客户端,默认将消息追踪打开了,果不其然:

所以需要联系微服务组将该参数改为可配置的,或者修改broker配置,将traceTopicEnable设置为true。

建议

由于RocketMQ客户端本身的日志也很庞大,每隔几秒就会刷新路由信息,可以将RocketMQ客户端的日志级别调低,来看源码是如何制定的:

所有可以在配置文件中指定日志级别和路径:

rocketmq:
  client:
    logRoot: ./logs/rmq
    logLevel: ERROR
    logFileName: rocketmq-client.log

总结

  • 出现该问题的根本原因在于:服务端不支持消息追踪的情况下,客户端设置enableMsgTrace=true

  • 由于服务端和客户端分属两个团队负责,并且业务方阐述问题并不是很明确,所以问题排查过程有些困难,需要熟悉客户端的配置及使用,便于以后更快定位问题

 

Guess you like

Origin blog.csdn.net/sinat_14840559/article/details/117336682