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添加相关的请求限流
相关推荐
烛阴4 小时前
bignumber.js深度解析:驾驭任意精度计算的终极武器
前端·javascript·后端
服务端技术栈4 小时前
电商营销系统中的幂等性设计:从抽奖积分发放谈起
后端
你的人类朋友5 小时前
✍️Node.js CMS框架概述:Directus与Strapi详解
javascript·后端·node.js
面朝大海,春不暖,花不开5 小时前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
钡铼技术ARM工业边缘计算机5 小时前
【成本降40%·性能翻倍】RK3588边缘控制器在安防联动系统的升级路径
后端
CryptoPP6 小时前
使用WebSocket实时获取印度股票数据源(无调用次数限制)实战
后端·python·websocket·网络协议·区块链
白宇横流学长6 小时前
基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
java·spring boot·后端
草捏子7 小时前
状态机设计:比if-else优雅100倍的设计
后端
考虑考虑8 小时前
Springboot3.5.x结构化日志新属性
spring boot·后端·spring
涡能增压发动积8 小时前
一起来学 Langgraph [第三节]
后端