问题描述

参考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未映射主机名产生的超时问题的更多相关文章

  1. 通过获取DNS解析的未转义主机名,区分测试环境和正式环境代码

    ASP.Net编程中经常有一些代码,测试环境下需要执行,而正式环境下不需要执行(或者反之). 我们经常做的方式是:去掉注释,测试,再注释,再编译上传(或者反之). 现在,不妨试试以下办法: Reque ...

  2. C#怎么得到主机名,IP,MAC

    一:基础知识 a: Dns 类 提供简单的域名解析功能. Dns 类是一个静态类,它从 Internet 域名系统 (DNS) 检索关于特定主机的信息. 在 IPHostEntry 类的实例中返回来自 ...

  3. Ubuntu18.04修改主机名和网卡地址

    date: 2019-06-26 09:56:04 author :headsen chen notice :个人原创 1,Ubuntu18.04 设置固定IP: 2,Ubuntu 18.04 设置主 ...

  4. CentOS6修改主机名(hostname)及 修改/etc/hosts 文件,增加ip和hostname的映射关系(转)

    CentOS修改主机名(hostname)  需要修改两处:一处是/etc/sysconfig/network,另一处是/etc/hosts,只修改任一处会导致系统启动异常.首先切换到root用户. ...

  5. Linux 修改主机名 和 ip 映射关系

    1. 修改主机名 vim /etc/sysconfig/network NETWORKING=yes HOSTNAME=hadoop 2. 修改主机名和IP的映射关系 vim /etc/hosts 1 ...

  6. linux的设置ip连接crt,修改主机名,映射,建文件

    1.修改IP(或者vim vi /etc/sysconfig/network-scripts/ifcfg-eth0) 2.连接 crt 3.修改主机名 用vim 编辑 /etc/sysconfig/n ...

  7. 无法启动T-SQL调试。未能连接到计算机"."。这是在主机名解析时通常出现的暂时错误……

    今天在按在SSMS中,按F11进行断点调试时,弹出错误:"无法启动T-SQL调试.未能连接到计算器".".这是在主机名解析时通常出现的暂时错误--", 如下图: ...

  8. Windows下主机名和IP映射设置

    如果需要添加域名和IP的对应关系可以在以下地方进行修改. 打开系统目录:c:/windows/system32/drivers/etc找到hosts文件,打开hosts文件并在最后面添加一条记录 例如 ...

  9. Java获取本地IP地址和主机名

    方式一:通过java.net.InetAddress类获取 public void test1() { try { InetAddress addr = InetAddress.getLocalHos ...

  10. CentOS7 设置主机名及IP映射

    1.设置主机名 查看本机的主机名,使用如下三个命令中任意一个即可 # hostname # uname -n # cat /proc/sys/kernel/hostname 使用 vi 编辑器打开 / ...

随机推荐

  1. IIS 实现autoindex的简单方法 能够下载文件等.

    之前使用nginx 的autoindex on 的参数 能够实现了 nginx的 目录浏览查看文件 但是那是linux上面的 windows 上面很多 使用的 其实是 iis的居多 然后看了下 其实也 ...

  2. 自己想的一些判断存储长度的sql

    create table zhaobsh (t1 date ,t2 TIMESTAMP) insert into zhaobsh values (CURRENT_DATE,CURRENT_TIMEST ...

  3. rabbitmq rpm包安装以及简单设置用户的方法

    公司有一台性能比较好的power机器. 同事要求安装rabbitmq 今天尝试进行了一下处理 公司里面有网络有相应的源 性能还不错 第一步安装一下依赖的erlang yum install erlan ...

  4. firewall-cmd 命令简单总结

    最近进行相关网络设置, 发现需要总结一下不然总是会忘记. # 1. 开放IP地址访问 firewall-cmd --zone=trusted --add-source=yourip --permane ...

  5. 容器方式运行Mysql8.0.26的方法

    容器化运行Mysql8.0.26测试环境的方法 1. 前言 之前为了好处理,都是二进制包的方式安装mysql,但是有时候需要下载和安装也比较费时费力, 今天中午在弄Oracle RAC时想着以后能够容 ...

  6. Spring Boot接口设计

    项目文件结构 编写示例代码 添加lombok的依赖 新建DemoController,用于提供RESTful接口.增加相关注解:@RestController,@RequestMapping(&quo ...

  7. 【JS 逆向百例】某网站加速乐 Cookie 混淆逆向详解

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 目标:加速乐加密 ...

  8. mysql系列14---mysql数据库还原与备份

    一.Liunx服务器下数据库定时备份 1.编写mysql在docker容器中备份的shell脚本: #!/bin/bash#  2020-11-15#docker启动的mysql备份mysql_use ...

  9. Gorm 入门介绍与基本使用

    Gorm 入门介绍与基本使用 目录 Gorm 入门介绍与基本使用 一.ORM简介 1.1 什么是ORM 1.2 使用ORM的好处 1.2.1 避免直接操作SQL语句 1.2.2 提高代码的可维护性 1 ...

  10. HTML超链接自定义颜色

    先添加一个css样式 我这里直接内嵌了因为代码量比较少不会影响太大的性能 <style type="text/css"> body {background-color: ...