本地啟動RocketMQ未映射主機名產(chǎn)生的超時問題最新解決方案
問題描述
參考RocketMQ官方文檔在本地啟動一個驗證環(huán)境的時候遇到超時報錯問題。
本地環(huán)境OS:CentOS Linux release 8.5.2111
首先,進入到RocketMQ安裝目錄,如:~/opt/rocketmq-all-5.2.0-bin-release
。
執(zhí)行如下命令啟動NameServer:
$ sh bin/mqnamesrv
該命令執(zhí)行很慢,但是最終還是顯示啟動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
執(zhí)行jps
命令也能看到相應(yīng)進程:
$ jps 13730 NamesrvStartup
執(zhí)行如下命令啟動Broker + Proxy:
$ sh bin/mqbroker -n localhost:9876 --enable-proxy
該命令執(zhí)行非常漫長,差不多要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參數(shù),如下所示:
brokerClusterName = DefaultCluster brokerName = broker-a # 配置的默認brokerName參數(shù) brokerId = 0 deleteWhen = 04 fileReservedTime = 48 brokerRole = ASYNC_MASTER flushDiskType = ASYNC_FLUSH
再次執(zhí)行jps
命令確認相應(yīng)進程是否已經(jīng)啟動:
$ jps jps 13730 NamesrvStartup 14410 ProxyStartup
一切似乎看起來都正常,從~/logs/rocketmqlogs/namesrv.log
和~/logs/rocketmqlogs/proxy.log
日志中也看不出明顯的異常。
但是在創(chuàng)建Topic時就會報錯:
$ sh bin/mqadmin updatetopic -n localhost:9876 -t TestTopic -c DefaultCluster
該命令在執(zhí)行大約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
,但是經(jīng)過驗證發(fā)現(xiàn)該地址是一定可以連通的,再幾經(jīng)嘗試之后依然報錯。
于是換了一臺Windows機器繼續(xù)驗證,奇怪的是在Windows機器上一切正常,而且我注意到在Windows環(huán)境啟動RocketMQ的時候brokerName使用是主機名,如下日志:
# zhangsan是主機名
The broker[zhangsan, 20.5.133.188:10911] boot success. serializeType=JSON and name server is localhost:9876
于是腦袋中突然閃現(xiàn)一個疑問,是不是因為沒有在CentOS的/etc/hosts
文件中映射主機名與127.0.0.1
地址導(dǎo)致的。
驗證后果然就正常的。
原因追蹤
根據(jù)相關(guān)報錯日志梳理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) { // 當(dāng)執(zhí)行時長超過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
,實際上該地址是可以連通的。
進一步追蹤發(fā)現(xiàn),是在執(zhí)行Netty的ReflectiveChannelFactory.newChannel()
方法耗時較長,約10s左右。
@Override public T newChannel() { try { // constructor是NioSocketChannel.class // 所以本質(zhì)上這里是要通過反射的方式實例化一個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));
執(zhí)行后輸出日志:
10144 ms
奇怪的是,當(dāng)在/etc/hosts
文件中明確指定主機名與127.0.0.1
的映射關(guān)系后,執(zhí)行就非常快。
暫時還不清楚這個地方的深層次原因是什么,為什么通過反射方式實例化NioSocketChannel
對象會跟主機名與127.0.0.1
的映射有關(guān)系呢?
【參考資料】
Windows 啟動RocketMQ
到此這篇關(guān)于本地啟動RocketMQ未映射主機名產(chǎn)生的超時問題的文章就介紹到這了,更多相關(guān)RocketMQ未映射主機名超時內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于SpringBoot?使用?Flink?收發(fā)Kafka消息的示例詳解
這篇文章主要介紹了基于SpringBoot?使用?Flink?收發(fā)Kafka消息,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01Java?多線程并發(fā)編程提高數(shù)據(jù)處理效率的詳細過程
這篇文章主要介紹了Java?多線程并發(fā)編程提高數(shù)據(jù)處理效率,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04新手入門Jvm-- JVM對象創(chuàng)建與內(nèi)存分配機制
JVM是Java Virtual Machine(Java虛擬機)的縮寫,JVM是一種用于計算設(shè)備的規(guī)范,它是一個虛構(gòu)出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的2021-06-06帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之隊列
這篇文章主要為大家介紹了Java數(shù)據(jù)結(jié)構(gòu)和算法之隊列,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01處理Log4j2不能打印行號的問題(AsyncLogger)
這篇文章主要介紹了處理Log4j2不能打印行號的問題(AsyncLogger),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12