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

3552 篇文章 107 订阅

缘起

访问线上的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线程池不够

所以又对集群进行了优化

  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添加相关的请求限流
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值