业务场景:车联网服务端使用Netty构建,接收车载终端的请求消息,然后下发给后端其它系统,最后返回应答给车载终端。
故障描述:系统运行一段时间后发现服务端接收不到车载终端消息,需要尽快定位出问题原因。
问题定位:首先查看服务端进程运行状态、JVM堆内存占用、CPU使用率、网络I/O等,各种资源占用率都不高,排除了系统压力过大导致请求消息无法及时处理的因素。
系统资源占用示例图:
排除资源耗尽等原因之外,可能导致无法接收请求消息的原因如下:
1、JVM 发生了长时间Full GC, 导致进程暂停;
2、Netty的NIO线程跑飞或者被意外阻塞,导致无法接收请求消息;
3、Netty 解码发生了异常,导致请求ByteBuf被赞包或者丢弃,无法解码到正常的业务消息;
4、其它异常。
按照顺序我们进行问题排查,首先查看Full GC对消息接收的影响,通过对GC的监控统计,发上故障期间,系统并没有发生Full GC,如下图所示:
问题根因:
排除Full GC故障之后,继续排查Netty的NIO线程,采集故障发生时线程的工作状态,如下图所示:NioEventLoop 3号线程组的1号线程被阻塞
Dump线程堆栈,发现Netty的NIO线程被后端业务自定义的阻塞队列阻塞:
原来是当转发给下游系统发生某些故障时,会导致业务定义的阻塞队列无法弹出消息进行处理,当队列积压满之后,就会阻塞Netty的NIO线程,而且无法自动恢复。定位出问题原因之后,对BUG进行修复,故障排除。
案例总结:
在任何情况下,都不能阻塞Netty的NIO线程,建议如下:
1、不要在Netty的NIO线程中做可能会导致阻塞的操作,例如同步磁盘I/O读写、数据库访问、FTP访问等;
2、消息由通信模块向业务逻辑传递时,往往使用线程池、消息队列等做线程切换,建议不要使用可能会导致同步阻塞的操作,例如阻塞队列的PUT方法。如果后端队列已满,可以使用动态流控、系统拥塞保护等机制,快速失败,而不是同步等待。
转:林之风 Netty之家林之风 N林之风 Netty之家
评论
暂无评论!
昵 称:
验证码:
内 容:
打赏
微信扫一扫,打赏一下~
关注公众号