RocketMQ的invokeSync call timeout异常的解决办法

简介: 在RocketMQ客户端的DefaultMQPushConsumer的start方法被执行时,时不时会报出invokeSync call timeout异常,如下:

缘起

在RocketMQ客户端的DefaultMQPushConsumer的start方法被执行时,时不时会报出invokeSync call timeout异常,如下:

Caused by: java.lang.IllegalStateException: org.apache.rocketmq.remoting.exception.RemotingTimeoutException: invokeSync call timeout
    at org.apache.rocketmq.client.impl.factory.MQClientInstance.updateTopicRouteInfoFromNameServer(MQClientInstance.java:679) ~[rocketmq-client-4.7.1.jar:4.7.1]
    at org.apache.rocketmq.client.impl.factory.MQClientInstance.updateTopicRouteInfoFromNameServer(MQClientInstance.java:509) ~[rocketmq-client-4.7.1.jar:4.7.1]
    at org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl.updateTopicSubscribeInfoWhenSubscriptionChanged(DefaultMQPushConsumerImpl.java:872) ~[rocketmq-client-4.7.1.jar:4.7.1]
    at org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl.start(DefaultMQPushConsumerImpl.java:653) ~[rocketmq-client-4.7.1.jar:4.7.1]
    at org.apache.rocketmq.client.consumer.DefaultMQPushConsumer.start(DefaultMQPushConsumer.java:698) ~[rocketmq-client-4.7.1.jar:4.7.1]
    at cn.xdf.xcloud.rocketmq.support.DefaultRocketMQListenerContainer.start(DefaultRocketMQListenerContainer.java:276) ~[xcloud-rocketmq-core-1.2.0.RELEASE.jar:1.2.0.RELEASE]
    at cn.xdf.xcloud.rocketmq.autoconfigure.ListenerContainerConfiguration.registerContainer(ListenerContainerConfiguration.java:103) ~[xcloud-rocketmq-core-1.2.0.RELEASE.jar:1.2.0.RELEASE]
    ... 12 common frames omitted
Caused by: org.apache.rocketmq.remoting.exception.RemotingTimeoutException: invokeSync call timeout
    at org.apache.rocketmq.remoting.netty.NettyRemotingClient.invokeSync(NettyRemotingClient.java:375) ~[rocketmq-remoting-4.7.1.jar:4.7.1]
    at org.apache.rocketmq.client.impl.MQClientAPIImpl.getTopicRouteInfoFromNameServer(MQClientAPIImpl.java:1363) ~[rocketmq-client-4.7.1.jar:4.7.1]
    at org.apache.rocketmq.client.impl.MQClientAPIImpl.getTopicRouteInfoFromNameServer(MQClientAPIImpl.java:1353) ~[rocketmq-client-4.7.1.jar:4.7.1]
    at org.apache.rocketmq.client.impl.factory.MQClientInstance.updateTopicRouteInfoFromNameServer(MQClientInstance.java:622) ~[rocketmq-client-4.7.1.jar:4.7.1]
    ... 18 common frames omitted

如果着急马上找到解决办法,可以直接跳到解决办法。不过,授人以鱼,不如授之以渔。还是建议把寻找解决办法的过程看完,第一:可以给你以后遇到类似问题提供解决思路;第二:虽然都报这个异常,但产生的原因可能不一样。

寻找解决办法之路

做为面向搜索引擎编程的一员,立马复制关键字invokeSync call timeout去搜索引擎,得到的解决办法总结起来有两点:

  1. RocketMQ客户端和服务端版本不一致,检查了一下客户端和服务端的版本,都是4.7.1。
  2. 降低RocketMQ客户端的版本,这个我时不能接受的。

搜索引擎无法解决,只能自己想办法了。首先找到报异常的地方:

    public RemotingCommand invokeSync(String addr, final RemotingCommand request, long timeoutMillis)
        throws InterruptedException, RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException {
        long beginStartTime = System.currentTimeMillis();
        final Channel channel = this.getAndCreateChannel(addr);
        if (channel != null && channel.isActive()) {
            try {
                doBeforeRpcHooks(addr, request);
                long costTime = System.currentTimeMillis() - beginStartTime;
                if (timeoutMillis < costTime) {
                    throw new RemotingTimeoutException("invokeSync call timeout");
                }
                RemotingCommand response = this.invokeSyncImpl(channel, request, timeoutMillis - costTime);
                doAfterRpcHooks(RemotingHelper.parseChannelRemoteAddr(channel), request, response);
                return response;
            }
            //省略部分无关代码
        } else {
            this.closeChannel(addr, channel);
            throw new RemotingConnectException(addr);
        }
    }

原来是因为代码执行的时间过长,才报出了invokeSync call timeout异常。首先想到的是延长超时时间,继续分析源码,向上寻找调用方,发现在MQClientInstanceupdateTopicRouteInfoFromNameServer方法中有:

topicRouteData = this.mQClientAPIImpl.getTopicRouteInfoFromNameServer(topic, 1000 * 3);

居然是写死了3秒,没有办法修改,我竟无语凝噎。

再向下一步一步地分析源码,到底是哪里慢?

org.apache.rocketmq.remoting.netty.NettyRemotingClient.getAndCreateChannel
org.apache.rocketmq.remoting.netty.NettyRemotingClient.getAndCreateNameserverChannel
org.apache.rocketmq.remoting.netty.NettyRemotingClient.createChannel
io.netty.bootstrap.Bootstrap.connect(java.net.SocketAddress)
io.netty.bootstrap.Bootstrap.doResolveAndConnect
io.netty.bootstrap.AbstractBootstrap.initAndRegister
io.netty.bootstrap.ChannelFactory.newChannel
io.netty.channel.socket.nio.NioSocketChannel.NioSocketChannel()
io.netty.channel.nio.AbstractNioChannel.AbstractNioChannel
io.netty.channel.AbstractChannel.AbstractChannel(io.netty.channel.Channel)
io.netty.channel.AbstractChannel.newId
io.netty.channel.DefaultChannelId.newInstance

最终找到了:

    public static DefaultChannelId newInstance() {
        return new DefaultChannelId();
    }

在创建DefaultChannelId的实例时,执行了这个类的静态代码块,就是这段静态代码块比较耗时。

那么,解决办法就有了,提前加载DefaultChannelId类,使其静态代码块先执行完成。

解决办法

在调用DefaultMQPushConsumer的start方法之前,插入如下代码:

DefaultChannelId.newInstance();
相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
Java
【MQTT异常】mqtt.inbound.MqttPahoMessageDrivenChannelAdapter Lost connection: 已断开连接; retrying...
【MQTT异常】mqtt.inbound.MqttPahoMessageDrivenChannelAdapter Lost connection: 已断开连接; retrying...
373 0
|
消息中间件 数据采集 缓存
性能调优篇:困扰我半年之久的RocketMQ timeout exception 终于被破解了
性能调优篇:困扰我半年之久的RocketMQ timeout exception 终于被破解了
性能调优篇:困扰我半年之久的RocketMQ timeout exception 终于被破解了
|
7月前
|
消息中间件 监控 Java
Spring Boot中的RabbitMQ死信队列魔法:从异常到延迟,一网打尽【RabbitMQ实战 一】
Spring Boot中的RabbitMQ死信队列魔法:从异常到延迟,一网打尽【RabbitMQ实战 一】
507 0
|
6月前
|
消息中间件 存储 负载均衡
消息队列 MQ产品使用合集之如何排查是哪个队列导致的异常TPS增加
阿里云消息队列MQ(Message Queue)是一种高可用、高性能的消息中间件服务,它允许您在分布式应用的不同组件之间异步传递消息,从而实现系统解耦、流量削峰填谷以及提高系统的可扩展性和灵活性。以下是使用阿里云消息队列MQ产品的关键点和最佳实践合集。
|
7月前
|
弹性计算 物联网 网络性能优化
MQTT常见问题之connection reset by peer 异常如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
7月前
|
消息中间件 物联网 定位技术
MQTT常见问题之使用 MQTT实例会报异常如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
7月前
|
消息中间件 RocketMQ 容器
rocketmq导致程序异常退出
2024-03-01 11:36:02.516 [Thread-7] INFO o.s.beans.factory.support.DisposableBeanAdapter - Invocation of destroy method failed on bean with name 'rocketMQTemplate': java.lang.IllegalStateException: Shutdown in progress 2024-03-01 11:36:02.517 [Thread-7] INFO o.s.beans.factory.support.DisposableBean
|
消息中间件 容器
RabbitMQ异常重启,部分消费队列不消费问题
RabbitMQ异常重启,部分消费队列不消费问题
482 0
|
消息中间件 弹性计算 运维
消息队列RocketMQ版:消费异常运维排查体验
本实验场景介绍消息队列RocketMQ版的可观测工具功能,通过示例程序模拟生产环境消费业务故障,并通过产品提供的开箱即用的可观测工具定位消费异常。
消息队列RocketMQ版:消费异常运维排查体验
|
消息中间件 存储 NoSQL
【2021年遇到最头疼的Bug】【Alibaba中间件技术系列】「RocketMQ技术专题」Broker配置介绍及发送流程、异常(XX Busy)问题分析总结
【2021年遇到最头疼的Bug】【Alibaba中间件技术系列】「RocketMQ技术专题」Broker配置介绍及发送流程、异常(XX Busy)问题分析总结
688 16
【2021年遇到最头疼的Bug】【Alibaba中间件技术系列】「RocketMQ技术专题」Broker配置介绍及发送流程、异常(XX Busy)问题分析总结