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添加相关的请求限流
相关推荐
渣哥8 分钟前
从代理到切面:Spring AOP 的本质与应用场景解析
javascript·后端·面试
文心快码BaiduComate24 分钟前
文心快码3.5S实测插件开发,Architect模式令人惊艳
前端·后端·架构
5pace29 分钟前
【JavaWeb|第二篇】SpringBoot篇
java·spring boot·后端
HenryLin30 分钟前
Kronos核心概念解析
后端
oak隔壁找我31 分钟前
Spring AOP源码深度解析
java·后端
货拉拉技术33 分钟前
大规模 Kafka 消费集群调度方案
后端
oak隔壁找我33 分钟前
MyBatis Plus 源码深度解析
java·后端
oak隔壁找我33 分钟前
Druid 数据库连接池源码详细解析
java·数据库·后端
剽悍一小兔34 分钟前
Nginx 基本使用配置大全
后端
LCG元34 分钟前
性能排查必看!当Linux服务器CPU/内存飙高,如何快速定位并"干掉"罪魁祸首进程?
linux·后端