Netty 面试难题分析

Netty 是如何解决 JDK 中的 Selector BUG 的?


Selector BUG:JDK NIO 的 BUG,例如臭名昭著的 epoll bug,它会导致 Selector 空轮询,
最终导致 CPU 100%。官方声称在 JDK1.6 版本的 update18 修复了该问题,但是直到 JDK1.7
版本该问题仍旧存在,只不过该 BUG 发生概率降低了一些而已,它并没有被根本解决,甚
至 JDK1.8 的 131 版本中依然存在。


JDK 官方认为这是 Linux Kernel 版本的 bug,可以参见:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6403933
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=2147719
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6670302
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6481709


简单来说,JDK 认为 linux 的 epoll 告诉我事件来了,但是 JDK 没有拿到任何事件(READ、
WRITE、CONNECT、ACCPET),但此时 select()方法不再选择阻塞了,而是选择返回了 0,于
是就会进入一种无限循环,导致 CPU 100%。


这个问题的具体原因是:在部分 Linux 的 2.6 的 kernel 中,poll 和 epoll 对于突然中断的
连接 socket 会对返回的 eventSet 事件集合置为 POLLHUP 或 POLLERR,eventSet 事件集合发
生了变化,这就可能导致Selector会被唤醒。但是这个时候selector的select方法返回numKeys
是 0,所以下面本应该对 key 值进行遍历的事件处理根本执行不了,又回到最上面的
while(true)循环,循环往复,不断的轮询,直到 linux 系统出现 100%的 CPU 情况,最终导致
程序崩溃。


Netty 解决办法:对 Selector 的 select 操作周期进行统计,每完成一次空的 select 操作
进行一次计数,若在某个周期内连续发生 N 次空轮询,则触发了 epoll 死循环 bug。重建
Selector,判断是否是其他线程发起的重建请求,若不是则将原 SocketChannel 从旧的 Selector
上去除注册,重新注册到新的 Selector 上,并将原来的 Selector 关闭。

摘自图灵课程学习笔记,分享出来共同学习、讨论

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值