本地启动RocketMQ未映射主机名产生的超时问题最新解决方案

 更新时间:2024年02月26日 08:54:20   作者:nuccch  
这篇文章主要介绍了本地启动RocketMQ未映射主机名产生的超时问题,本文给大家分享最新解决方案,感兴趣的朋友跟随小编一起看看吧

问题描述

参考RocketMQ官方文档在本地启动一个验证环境的时候遇到超时报错问题。

本地环境OS:CentOS Linux release 8.5.2111

首先,进入到RocketMQ安装目录,如:~/opt/rocketmq-all-5.2.0-bin-release

执行如下命令启动NameServer:

$ sh bin/mqnamesrv

该命令执行很慢,但是最终还是显示启动NameServer成功了,输出日志如下:

Java HotSpot(TM) 64-Bit Server VM warning: Using the DefNew young collector with the CMS collector is deprecated and will likely be removed in a future release
Java HotSpot(TM) 64-Bit Server VM warning: UseCMSCompactAtFullCollection is deprecated and will likely be removed in a future release.
The Name Server boot success. serializeType=JSON, address 0.0.0.0:9876

执行jps命令也能看到相应进程:

$ jps
13730 NamesrvStartup

执行如下命令启动Broker + Proxy:

$ sh bin/mqbroker -n localhost:9876 --enable-proxy

该命令执行非常漫长,差不多要90s左右才会输出如下日志:

Sat Feb 24 19:48:03 CST 2024 rocketmq-proxy startup successfully

~/logs/rocketmqlogs/proxy.log日志中也能看到broker启动成功的日志:

2024-02-24 19:47:53 INFO main - The broker[broker-a, 192.168.88.135:10911] boot success. serializeType=JSON and name server is localhost:9876

注意:日志中的broker-a是在broker.conf文件中配置的brokerName参数,如下所示:

brokerClusterName = DefaultCluster
brokerName = broker-a # 配置的默认brokerName参数
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH

再次执行jps命令确认相应进程是否已经启动:

$ jps
jps
13730 NamesrvStartup
14410 ProxyStartup

一切似乎看起来都正常,从~/logs/rocketmqlogs/namesrv.log~/logs/rocketmqlogs/proxy.log日志中也看不出明显的异常。

但是在创建Topic时就会报错:

$ sh bin/mqadmin updatetopic -n localhost:9876 -t TestTopic -c DefaultCluster

该命令在执行大约40s左右就会输出如下报错日志:

org.apache.rocketmq.tools.command.SubCommandException: UpdateTopicSubCommand command failed
        at org.apache.rocketmq.tools.command.topic.UpdateTopicSubCommand.execute(UpdateTopicSubCommand.java:198)
        at org.apache.rocketmq.tools.command.MQAdminStartup.main0(MQAdminStartup.java:164)
        at org.apache.rocketmq.tools.command.MQAdminStartup.main(MQAdminStartup.java:114)
Caused by: org.apache.rocketmq.remoting.exception.RemotingTimeoutException: invokeSync call the addr[127.0.0.1:9876] timeout
        at org.apache.rocketmq.remoting.netty.NettyRemotingClient.invokeSync(NettyRemotingClient.java:549)
        at org.apache.rocketmq.client.impl.MQClientAPIImpl.getBrokerClusterInfo(MQClientAPIImpl.java:1961)
        at org.apache.rocketmq.tools.admin.DefaultMQAdminExtImpl.examineBrokerClusterInfo(DefaultMQAdminExtImpl.java:577)
        at org.apache.rocketmq.tools.admin.DefaultMQAdminExt.examineBrokerClusterInfo(DefaultMQAdminExt.java:318)
        at org.apache.rocketmq.tools.command.CommandUtil.fetchMasterAddrByClusterName(CommandUtil.java:94)
        at org.apache.rocketmq.tools.command.topic.UpdateTopicSubCommand.execute(UpdateTopicSubCommand.java:171)
        ... 2 more

从报错信息看似乎是无法连接127.0.0.1:9876,但是经过验证发现该地址是一定可以连通的,再几经尝试之后依然报错。

于是换了一台Windows机器继续验证,奇怪的是在Windows机器上一切正常,而且我注意到在Windows环境启动RocketMQ的时候brokerName使用是主机名,如下日志:

# zhangsan是主机名
The broker[zhangsan, 20.5.133.188:10911] boot success. serializeType=JSON and name server is localhost:9876

于是脑袋中突然闪现一个疑问,是不是因为没有在CentOS的/etc/hosts文件中映射主机名与127.0.0.1地址导致的。

验证后果然就正常的。

原因追踪

根据相关报错日志梳理RocketMQ的源代码,报错是因为在NettyRemotingClient.invokeSync()方法中做了超时判断。

@Override
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);
    String channelRemoteAddr = RemotingHelper.parseChannelRemoteAddr(channel);
    if (channel != null && channel.isActive()) {
        long left = timeoutMillis; // 默认超时时长是5000ms
        try {
            long costTime = System.currentTimeMillis() - beginStartTime;
            left -= costTime;
            if (left <= 0) { // 当执行时长超过5s时直接抛出异常
                throw new RemotingTimeoutException("invokeSync call the addr[" + channelRemoteAddr + "] timeout");
            }
            RemotingCommand response = this.invokeSyncImpl(channel, request, left);
            updateChannelLastResponseTime(addr);
            return response;
        }
        //其他代码省略...
    }
    //其他代码省略...
}

由于是做了超时检查抛出的异常,所以单纯从日志信息看就会认为是无法连接127.0.0.1:9876,实际上该地址是可以连通的。

进一步追踪发现,是在执行Netty的ReflectiveChannelFactory.newChannel()方法耗时较长,约10s左右。

@Override
public T newChannel() {
    try {
        // constructor是NioSocketChannel.class
        // 所以本质上这里是要通过反射的方式实例化一个NioSocketChannel对象
        T t = constructor.newInstance();
        return t;
    } catch (Throwable t) {
        throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
    }
}

验证代码如下:

long start = System.currentTimeMillis();
Constructor constructor = NioSocketChannel.class.getConstructor();
constructor.newInstance();
System.out.println(String.format("%s ms", System.currentTimeMillis() - start));

执行后输出日志:

10144 ms

奇怪的是,当在/etc/hosts文件中明确指定主机名与127.0.0.1的映射关系后,执行就非常快。

暂时还不清楚这个地方的深层次原因是什么,为什么通过反射方式实例化NioSocketChannel对象会跟主机名与127.0.0.1的映射有关系呢?

【参考资料】
Windows 启动RocketMQ

到此这篇关于本地启动RocketMQ未映射主机名产生的超时问题的文章就介绍到这了,更多相关RocketMQ未映射主机名超时内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Springboot详解线程池与多线程及阻塞队列的应用详解

    Springboot详解线程池与多线程及阻塞队列的应用详解

    本例应用线程池、多线程、阻塞队列处理一个流程任务。本例处理一个订单流程,主要包括生成订单、订单处理、订单入库,下面我们一起看看
    2022-06-06
  • Java的包装类特性总结

    Java的包装类特性总结

    这篇文章主要介绍Java的包装类的一些特性,包装类的作用,哪些类属于包装类等,文中有详细的代码示例,对我们的学习或工作有一定的帮助,需要的朋友可以参考下
    2023-05-05
  • java中表示一个文件的File类型详解

    java中表示一个文件的File类型详解

    Java提供File类,让我们对文件进行操作,下面这篇文章主要给大家介绍了关于java中表示一个文件的File类型的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-07-07
  • 通俗易懂学习java并发工具类-Semaphore,Exchanger

    通俗易懂学习java并发工具类-Semaphore,Exchanger

    这篇文章主要介绍了java并发工具类-Semaphore,Exchanger,java并发工具类有很多,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面小编带大家来一起学习一下吧
    2019-06-06
  • 2020最新 idea下载、安装与创建项目测试的教程图解

    2020最新 idea下载、安装与创建项目测试的教程图解

    这篇文章主要介绍了2020最新 idea下载、安装与创建项目测试的教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Java+opencv3.2.0实现人脸检测功能

    Java+opencv3.2.0实现人脸检测功能

    这篇文章主要为大家详细介绍了Java+opencv3.2.0实现人脸检测功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Spring @Autowired注解超详细示例

    Spring @Autowired注解超详细示例

    @Autowired注解可以用在类属性,构造函数,setter方法和函数参数上,该注解可以准确地控制bean在何处如何自动装配的过程。在默认情况下,该注解是类型驱动的注入
    2022-08-08
  • springboot中JSONObject遍历并替换部分json值

    springboot中JSONObject遍历并替换部分json值

    这篇文章主要介绍了springboot中JSONObject遍历并替换部分json值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 详解Java中字典树(Trie树)的图解与实现

    详解Java中字典树(Trie树)的图解与实现

    Trie又称为前缀树或字典树,是一种有序树,它是一种专门用来处理串匹配的数据结构。本文将利用图解详细讲解Trie树的实现,需要的可以参考一下
    2022-05-05
  • Spring Bean的线程安全问题

    Spring Bean的线程安全问题

    Spring容器中的Bean是否线程安全,本文主要介绍了Spring Bean的线程安全问题,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06

最新评论