RocketMQ集群突发大量超时问题排查及优化

这里是weihubeats ,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党

缘起

访问线上的RocketMQ集群的dashboard突然上不去了提示超时

初次排查

看报错很清晰可以看到就是timeout

所以最简单的是增加了超时时间(我多等一会),从5s增加到10s15s

但是发现并没有什么用,还是超时

这时候初步怀疑是网络问题

查看RocketMQ log

这时候没什么其他办法,只能去服务器上面看看有没有错误log

发现服务器存在大量报错log

java 复制代码
at io.netty.channel.AbstractChannel$AbstractUnsafe.write(ObjectChannelPromise)(Unknown Source)
08-18 19:43:53 ERROR NettyServerNIOSelector_3_2 - Failed to write ressponse[request code: 41, response code: 0, opaque: 166429356] to chanel[id: 0xc0b80baf, L:/192.168.1:30911
R:/192.168.2:56824]

这里可以看到的错误就是RocketMQ broker一直想要将client请求的数据响应给client,但是client都没有接受这个响应,因为brokerclient之间的连接已经关闭了 大致流程如下

所以这里看到的情况就是服务端一直在报错

client一直向broker发送请求,但是这些请求broker处理了,client却在接收响应前断开连接了

这个错误会导致dashboard连接不上吗?单看这个log并不能看出问题,我们再看看RocketMQremote.log文件看看,发现有大量的channelGegistered

java 复制代码
2023-08-18 20:26:57 INFO NettyServerCodecThread_8 - NETTY SERVER PIPELINE: channelRegistered 192.168.1.12:60912
2023-08-18 20:26:58 INFO NettyServerCodecThread_6 - NETTYSERVER PIPELINE: channelRegistered 192.168.1.12:60914
2023-08-18 20:26:59 INFO NettyServerCodecThread_5 - NETTYSERVER PIPELINE: channelRegistered 192.168.1.12:609968
2023-08-18 20:27:00 INFO NettyServerCodecThread_4 - NETTYSERVER PIPELINE: channelRegistered 192.168.1.12:58374
2023-08-18 20:27:01 INFO NettyServerCodecThread_2 - NETTY SERVER PIPELINE: channelRegistered 192.168.1.12:37832

这里发现有个问题,有个客户端192.168.1.12一直在重复注册,也就是重复建立连接

猜测可能是BossGroup被打满一直占用着

RocketMQ 线程池模型

我们知道RocketMQ的远程通信线程模型是 1+N+M+M

这一块的线程模型可以给大家看看源码

可以看到boosGroup是一个

这里可以看到workGroup是多个,实际在wrokGroup还有再分多个线程池去处理不同的业务逻辑

由于boosGroup是一个,所以存在boosGroup被打满的情况,导致dashboard连接不上超时

查看linux tcp连接情况

为了确认这个猜想,我这里查看了linux机器上的tcp连接数量

arduino 复制代码
watch -n 1 'netstat -nat | grep ESTABLISHED | wc -l'

会发现打印出来的tcp连接数量一直在变化(一直增加又减少),说明一直在断线重连

断线重连问题排查

为什么client要一直断线重连呢

这里我们查看源码发现client如果发生超时,就会断线。再次请求就需要重新建立连接

我们去查看brokerlog也发现了大量的关闭socket log

perl 复制代码
invokeSync: close socket because of timeout

阿里云 client sdk与开源版本的差异

我们查看源码发现阿里云商业版本的sdk如果超时并不会断开连接

所以只有开源版本才会出现这个问题。

为了解决断线重连的问题,所以client添加如下配置

arduino 复制代码
System.setProperty(COM_ROCKETMQ_REMOTING_CLIENT_CLOSE_SOCKET_IF_TIMEOUT, "false");

client断线重连解决

添加参数后会发现不存在client断线重连的log,但是还有如下问题

  1. dashboard还是偶尔能连接上
  2. client的超时问题并没有解决,只是解决了超时不断线重连
  3. broker仍然存在断线重连

这里还是以为BossGroup被打满

由于线上的RocketMQ集群主从同步之间仍然存在断线重连

其次线上RocketMQ 集群不能随便重启,也不能随便修改代码。所以不打算添加client之前添加的配置

java 复制代码
System.setProperty(COM_ROCKETMQ_REMOTING_CLIENT_CLOSE_SOCKET_IF_TIMEOUT, "false");

再次怀疑是网络问题

这次猜想是可能是主从机器之间网络出了问题

为了更加严谨快速验证,打算用goland写一个clientserver进行tcp连接,然后仅发送心跳

server核心代码如下

结果验证

可以看到网络耗时都在1ms左右,所以其实两台机器网络都没问题

怀疑是堆外内存不够、serverSelectorThreads、serverWorkerThreads不够

检查线上的RocketMQ部署实际给到的jvm内存为宿主机的90%,但是RocketMQ使用使用了大量的堆外内存。

其次在网上看到一篇博文也是遇到类似的问题说是 serverSelectorThreadsserverWorkerThreads线程池不够

博文链接: developer.aliyun.com/article/942...

所以又对集群进行了优化

  1. 优化JVM启动参数
  2. 优化Netty bossGroup为EpollEventLoopGroup
  3. 增大serverSelectorThreads和serverWorkerThreads

然后重启部署

结果: 问题还是没解决

排除网络问题

每天茶饭不思,突然突发灵感。

我在broker这台机器发送请求自己,如果响应还是超时,那么就可以确定不是网络问题

在broker执行如下脚本

shell 复制代码
 ./mqadmin getBrokerConfig -n 127.0.0.1:9000 -c xiaozou

发现还是broker自己请求自己 还是超时

所以可以确定一定不是网络问题

是否gc导致的

检查服务端gccpu内存请求

发现都是非常正常,且低频的,没有任何异常

arthas加入战场

为了定位到到底是哪里导致的超时,使用了arthas进行了方法耗时追踪

发现整个请求基本在240ms就完成了,根本不会超过5s

抓取整个逻辑代码的处理

发现代码的耗时只要是在异步转同步

这里实际是又开了一个线程池去处理请求

也就就是1+n+m里面的M

这里初步怀疑是M线程池(AdminBrokerThread_)满了导致的

随即使用arthas抓取线程池里面的任务

css 复制代码
vmtool --action getInstances --className org.apache.rocketmq.broker.latency.BrokerFixedThreadPoolExecutor --limit 100 --express "instances[5].workQueue.{#this.runnable}" -x 2

然后发现大量堆积任务

再次使用arthas看看queue里面堆积了多少个任务

css 复制代码
vmtool --action getInstances --className org.apache.rocketmq.broker.latency.BrokerFixedThreadPoolExecutor --limit 100 --express "instances[5]"

发现workQueue还在一直增加

总结

这里真相水落石出了,主要是还是(AdminBrokerThread_)线程池被打满堆积了太多任务导致的

如何处理呢

  1. 增大(AdminBrokerThread_)线程池
  2. 减少对(AdminBrokerThread_)线程池的请求
  3. (AdminBrokerThread_)线程池添加监控
  4. broker添加相关的请求限流
相关推荐
2401_854391087 分钟前
城镇住房保障:SpringBoot系统功能概览
java·spring boot·后端
陈随易12 分钟前
兔小巢收费引发的论坛调研Node和Deno有感
前端·后端·程序员
聪明的墨菲特i17 分钟前
Django前后端分离基本流程
后端·python·django·web3
hlsd#1 小时前
go mod 依赖管理
开发语言·后端·golang
陈大爷(有低保)1 小时前
三层架构和MVC以及它们的融合
后端·mvc
亦世凡华、1 小时前
【启程Golang之旅】从零开始构建可扩展的微服务架构
开发语言·经验分享·后端·golang
河西石头1 小时前
一步一步从asp.net core mvc中访问asp.net core WebApi
后端·asp.net·mvc·.net core访问api·httpclient的使用
2401_857439691 小时前
SpringBoot框架在资产管理中的应用
java·spring boot·后端
怀旧6661 小时前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
阿华的代码王国2 小时前
【SpringMVC】——Cookie和Session机制
java·后端·spring·cookie·session·会话