当 Thrift 遇到 JDK Epoll Bug

本文详述了在使用Thrift作为RPC框架时遇到的JDKEpollBug问题及其定位过程。作者通过压测发现问题,并借助jstack工具定位到了Thrift的TThreadedSelectorServer.select()方法触发了此Bug。最终通过重建Selector并注册所有事件的方式成功解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

##前言 相信不少 Java server 端程序深受臭名昭著的 JDK Epoll Bug 其害。一旦触发所有 Selector 线程处于空转状态不能自拔,直至 cpu 跑满,不再处理外来连接。对于外部调用者来说这意味着服务不可用,这真是一场灾难。

笔者不才,前段时间在使用 Thrift 作为 server 端 rpc 框架对外提供服务时刚好触发了此 bug ,在此记录定位问题的过程和解决办法,供各位参考,望再有后来人碰到此问题不在受此困扰。话不多说,先来复盘。

问题定位

话说服务端程序都已开心码完,在做最后的压测时,突然发现压测程序请求不到服务直至访问超时。赶紧到所在服务器查看服务状况,结果发现多个 cpu 跑满了,如下图:

cpu run full

于是赶紧用 top -Hp $PID 查看下所在进程的线程情况,结果如下图:

thread info in progress

按 cpu 使用量排序后,发现前面几个线程 cpu 使用量接近 100% 。 Java 程序快用 jstack 查看这个线程在干嘛吧,定位到 pid=177 ( 0xb1 ) 的线程堆栈信息如下:

thread details

从堆栈信息可以看到触发点位于 Thrift 的 TThreadedSelectorServer.select() 方法中,查看源码可知其不过是调用了JDK Selector.select() 方法。(注:为描述方便笔者把实例方法调用使用类方法调用形式展示)

TThreadedSelectorServer.select()

看现象初步认为是压测时连接数过多导致 Selector 线程一直处于繁忙状态,可后来发现停掉压测 cpu 使用量还是居高不下。

笔者曾一度陷入困境,后经高人同事提点道:会不会是JDK Epoll Bug ?我一想这个 bug 官方不是修复了吗,后来查证发现:官方声称在JDK1.6版本的update18修复了该问题,然而只是降低了发生的概率而已,它并没有被根本解决。该 bug 以及相关的问题如下:

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6403933

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=2147719

笔者当时环境为:

work JRE

看来到 jdk 1.8 这个问题也没解决,为 Oracle 感到小小的尴尬啊。

解决办法

JDK 的 bug 让使用者极其的尴尬啊,因为我们又不能更改其源码。好在好的搜索引擎拉低了学习的门槛,在茫茫互联网中帮我找到了一位高人总结的解决办法,其中有详细写明触发原因及解决办法,详见:

应用服务器中对JDK的epoll空转bug的处理

笔者简述下解决办法:

  1. 确认程序触发 epoll bug :在一定时间间隔内触发了设定阈值次数的空转,则认定触发 epoll bug
  2. 修复:通过重建 Selector 方式,新 Selector 注册问题 Selector 所有事件后替换它。

定位到问题及知道解决办法后,接下来就赶紧修复它吧。

按照 Thrift 官方 Developers 贡献指南一步步来:

至此问题修复完成。感兴趣者可以关注上述 issue 来获取官方修复的最新进展。

参考博客:

应用服务器中对JDK的epoll空转bug的处理

Java NIO通信框架在电信领域的实践

转载此博客请注明来源:https://my.oschina.net/johnnyliao/blog/1507141

转载于:https://my.oschina.net/farces/blog/1585423

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值