RocketMQ生产问题一般如何排查?

2023-03-03 17:45:29 浏览数 (1)

从RocketMQ架构来看,用户在使用客户端生产时时不时会遇到一些问题,这里做了一些总结,大家参考

初始化生产者实例报错

在使用rocketmq spring boot starter或者rocketmq client时,很容易创建多个相同实例或者同一个实例启动多次,导致出现以下报错:

第一个可能出现的问题: The producer service state not OK, maybe started once, RUNNING

代码语言:txt复制
Exception in thread "main" org.apache.rocketmq.client.exception.MQClientException: The producer service state not OK, maybe started once, RUNNING
See https://rocketmq.apache.org/docs/bestPractice/06FAQ for further details.
	at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.start(DefaultMQProducerImpl.java:251)
	at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.start(DefaultMQProducerImpl.java:212)
	at org.apache.rocketmq.client.producer.DefaultMQProducer.start(DefaultMQProducer.java:299)
	at org.apache.rocketmq.example.simple.Producer.main(Producer.java:38)

排查分析:一般这种是同一个实例调用了多次start方法导致的。在spring中,需要排查在初始化bean时是否主动调用了多次start方法、是否spring和自己的代码都调用了start。spring可以显示调用,也可以注册bean的初始化方法。

具体逻辑可以参看Producer启动代码:

第二个可能出现的问题:The producer service state not OK, maybe started once, SHUTDOWN_ALREADY

代码语言:txt复制
Exception in thread "main" org.apache.rocketmq.client.exception.MQClientException: The producer service state not OK, maybe started once, SHUTDOWN_ALREADY
See https://rocketmq.apache.org/docs/bestPractice/06FAQ for further details.
	at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.start(DefaultMQProducerImpl.java:251)
	at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.start(DefaultMQProducerImpl.java:212)
	at org.apache.rocketmq.client.producer.DefaultMQProducer.start(DefaultMQProducer.java:299)
	at org.apache.rocketmq.example.simple.Producer.main(Producer.java:41)
Disconnected from the target VM, address: '127.0.0.1:51268', transport: 'socket'

排查分析:一般这种原因是调用了shutdown方法后,又调用了start。

一般我们惯性思维觉得是没问题的,其实rocketmq中producer和consumer的初始化过程是:初始化 start、shutdown。所以shutdown后需要初始化 start,初始化过程只有在新建实例的时候才做。

一般可以复用相同producer实例,或者shutdown后再使用时new新实例。在一些流计算的算子中,可能会使用new新实例的方式。

代码参看

对于上面的代码我们简要解释下: 每个RocketMQ客户端进程会拥有一个MQClientInstance实例并且是单例,每个单例里面保存了这个客户端的全部生产者,也就是第二个图中的producerTable,如果有重复的生产者注册进来会注册失败。

topic路由信息获取不到: No topic route info in name server for the topic: XXXX

客户端发送获取路由,发送消息的流程图如下:

RocketMQ通信架构图RocketMQ通信架构图

生产者发送消息的步骤可以简单分为:

  • 启动生产者,启动路由定时更新检查线程, 检查缓存topicPublishInfoTable中的topic的路由信息是否变化
  • 用户第一次调用生产者send方法,send方法内部查询topicPublishInfoTable缓存,发现没有路由,立即调用tryToFindTopicPublishInfo方法获取topic的路由,保存到topicPublishInfoTable,发送消息。
  • 用户第二次调用生产者send方法,send方法内部查询topicPublishInfoTable缓存,发现存在路由,立即发送消息。

注意:topicPublishInfoTable可以认为是最新的路由信息。topicPublishInfoTable中的路由信息由路由定时更新检查线程定时检查维护, 如果namesrv有最新的路由,它会更新topicPublishInfoTable。

有了以上知识,我们看可能遇到的问题。

topic不存在或者路由信息获取不到

获取到的路由信息为空, 客户端会报错,可能topic没有创建,导致没有获取到topic信息。可能topic创建的时候通知Namesrv失败了, Namesrv没有保存这个topic的路由信息,查询也就返回空。

这种情况新建topic或者删除新建, 实在不行重启namesrv后,再删除新建。

这个逻辑可以追溯到Namesrv的查询路由信息的代码说起:

Namesrv查询路由的代码如下:

image.pngimage.png

Namesrv内存中的路由信息从架构图可以看出时Broker定期上报的,如果没有上报或者压根儿没有这个topic,topic路由不存在就是预期内的。

发送消息失败,如上图中03到02。

原因很多, 这里例举常见的问题:

  • 客户端访问Broker网络不通 这种情况客户端处理不了,最好找服务维护人员
  • 发送到Broker报错 可能的问题和分析处理:在确定可以ping通Broker后,一般Broker报错会有错误信息,比如超时、broker磁盘满、broker同步slave失败等,需要根据返回的错误信息排查Broker代码。 这时把本地~/logs/rocketmqlogs/rocketmq_client.log和返回报错信息准备好,丢给运维rocketmq的同学吧。

以上是生产报错, 下一篇我们分享消费失败的问题排查方式。

生产耗时比较大怎么定位?

https://cloud.tencent.com/developer/article/2192667

0 人点赞