NIO的epoll空轮询bug

Netty是如何解决JDK空轮询Bug的? Selector每一次轮询都计数selectCnt++,开始轮询会将系统时间戳赋值给timeoutMillis,轮询完成后再将系统时间戳赋值给time,这两个时间会有一个时间差,而这个时间差就是每次轮询所消耗的时间。这是与操作系统机制有关系的,JDK虽然仅仅是一个兼容各个操作系统平台的软件,但遗憾的是在JDK 5和JDK 6最初的版本中,这个问题并没有得到解决,而将这个“帽子”抛给了操作系统方,这就是这个Bug一直到2013年才最终修复的原因。就这样,Netty完美解决了JDK的空轮询Bug。 阅读详情

JDK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该BUG发生概率降低了一些而已,它并没有被根本解决。该BUG以及与该BUG相关的问题单可以参见以下链接内容。

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

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

参考:https://github.com/netty/netty/issues/327

参考:https://www.jianshu.com/p/d0f06b13e2fb

参考:http://blog.jobbole.com/105564/

参考:http://blog.youkuaiyun.com/xyls12345/article/details/26571699

Selector BUG出现的原因

若Selector的轮询结果为空,也没有wakeup或新消息处理,则发生空轮询,CPU使用率100%,

Netty的解决办法

  • 对Selector的select操作周期进行统计,每完成一次空的select操作进行一次计数,

  • 若在某个周期内连续发生N次空轮询,则触发了epoll死循环bug。

  • 重建Selector,判断是否是其他线程发起的重建请求,若不是则将原SocketChannel从旧的Selector上去除注册,重新注册到新的Selector上,并将原来的Selector关闭。

 

参考:http://blog.youkuaiyun.com/baiye_xing/article/details/73351330

 

前面讲到了epoll的一些机制,与select和poll等传统古老的IO多路复用机制的一些区别,这些区别实质可以总结为一句话,

就是epoll将重要的基于事件的fd集合放在了内核中来完成,因为内核是高效的,所以很多关于fd事件监听集合的操作也是高效的,

不方便的就是,因为在内核中,所以我们需要通过系统调用来调用关于fd操作集合,而不是直接自己攒一个。

如果在linux中,epoll在JDK6中还需要配置,在后续的版本中为JDK的NIO提供了默认的实现,但是epoll在JDK中的实现却是漏洞百出的,

bug非常的多,比较容易复现并且被众多人诟病的就是epoll轮询的处理方法。

sun的bug列表为:

JDK-6670302 (se) NIO selector wakes up with 0 selected keys infinitely [lnx 2.4]

JDK-6670302 : (se) NIO selector wakes up with 0 selected keys infinitely [lnx 2.4]

===》这个bug的描述内容为,在NIO的selector中,即使是关注的select轮询事件的key为0的话,NIO照样不断的从select本应该阻塞的

情况中wake up出来,也就是下图中的红色阻塞的部分:


 

然后,因为selector的select方法,返回numKeys是0,所以下面本应该对key值进行遍历的事件处理根本执行不了,又回到最上面的while(true)循环,循环往复,不断的轮询,直到linux系统出现100%的CPU情况,其它执行任务干不了活,

最终导致程序崩溃。

==》从这个bug上来看,这个绝对是JDK中的问题,select方法就应该是阻塞的,没有key事件过来,那么就不应该返回,和应用程序的写法没有任何的关系,与之相差不多的一个bug给出了解决的方案:

JDK-6403933 (se) Selector doesn't block on Selector.select(timeout) (lnx)

JDK-6403933 : (se) Selector doesn't block on Selector.select(timeout) (lnx)

这个bug的意思基本上和前面的JDK-6670302相差不大,也是Selector不阻塞,前一个bug说明的是最终的现象,

这个JDK-6403933的bug说出了实质的原因:

具体解释为,在部分Linux的2.6的kernel中,poll和epoll对于突然中断的连接socket会对返回的eventSet事件集合置为POLLHUP,也可能是POLLERR,eventSet事件集合发生了变化,这就可能导致Selector会被唤醒。==》这是与操作系统机制有关系的,JDK虽然仅仅

是一个兼容各个操作系统平台的软件,但很遗憾在JDK5和JDK6最初的版本中(严格意义上来将,JDK部分版本都是),这个问题并没有解决,而将这个帽子抛给了操作系统方,这也就是这个bug最终一直到2013年才最终修复的原因,最终影响力太广。

修复的方法,在这个bug中已经提到了:

上面是第一个建议,首先将SelectKey去除掉,然后“刷新”一下Selector,刷新的方式也就是调用Selector.selectNow方法,

这个示意的代码如下:

这段代码意味着重置,首先将SelectionKey注销掉,然后重新调用非阻塞的selectNow来让Selector换取“新生”。

这种修改方式就是grizzly的commiteer们最先进行修改的,并且通过众多的测试说明这种修改方式大大降低了JDK NIO的问题。

但是,这种修改仍然不是可靠的,一共有两点:

1.多个线程中的SelectionKey的key的cancel,很可能和下面的Selector.selectNow同时并发,如果是导致key的cancel后运行很可能没有效果

2.与其说第一点使得NIO空转出现的几率大大降低,经过Jetty服务器的测试报告发现,这种重复利用Selector并清空SelectionKey的改法很可能没有任何的效果,

最终的终极办法是创建一个新的Selector:

具体的Jetty服务器的分析地址为:

Jetty/Feature/JVM NIO Bug

Jetty首先定义两了-D参数:

  • org.mortbay.io.nio.JVMBUG_THRESHHOLD, defaults to 512 and is the number of zero select returns that must be exceeded in a period.

  • org.mortbay.io.nio.MONITOR_PERIOD defaults to 1000 and is the period over which the threshhold applies.

第一个参数是select返回值为0的计数,第二个是多长时间,整体意思就是控制在多长时间内,如果Selector.select不断返回0,说明进入了JVM的bug的模式

那么,Jetty这时候就有所作为了,我们看到Jetty的具体的代码如下:

首先,根据-D参数判断是否进入了JAVA NIO空转的bug模式,一个是判断时间,一个是判断次数,次数通过-jvmBug作为计数器进行统计;如果一旦确定是bug,可以看到上述代码为了防止并发出现,加了Sychronized锁,接着开启一个新的Selector,并将原有的SelectionKey的事件全部转移到了新的Selector中,最后将-jvmBug计数器置0;

==》这种处理方法要保险的多,基本上不会有任何的问题了,

Jetty在这个网页中还提供了很多参数,如:

即使上述的处理方式,对应极少的linux环境和JDK的版本,仍会出现一些问题,这主要是因为网络中断的间隔时间太短造成的,需要给内核一定的时钟周期进行缓冲,而上述的Jetty的org.mortbay.io.nio.BUSY_PAUSE这个参数就是起到间隔的作用,间隔多少微秒再调用Select,这样基本上能最大程度上避免上述问题出现了。

从上面Jetty各种处理方法来看,基本能屏蔽低版本JDK和操作系统的epoll的影响,让NIO可以无忧运行。当然,对于NIO框架也是修正了这些错误,前面提到的Griizzly和Netty都对这个问题采取了响应的策略。

以Netty为例,具体位置在NioSelector的实现类AbsNioSelector中:

上述的思路和Jetty的处理方式几乎是一样的,就是netty讲重建Selector的过程抽取成了一个方法,叫做rebuildSelector,可以看看其方法:

基本上类似,这里就不再缀余。

分析到这里,可以看到为什么NIO框架如Netty,Grizzly,还有最近的炒得很热的Jboss的UnderTow,NIO远远不止这篇文章分析得这一个,还有很多,大可在JDK官网上去查,而这些框架都将NIO的很多不好用的问题,bug隐藏起来了,并加上诸如限流,字符转换,基于设计模式等特性,让开发人员更好的编写高并发的程序,而不用过多的网络的关注与细节。

由此可见,现在JAVA真是越来越危机了,从前几年的SSH把java ee给替换掉,到现在jdk都时不时冒出一个bug来,而且最近JDK8中的一个bug大有超过这个bug之势,jcp社区确实需要好好反省了,要不然java没落了,一干程序员又得下岗再就业了。

总结:

NIO的空转bug历史悠久流传广泛,应用服务器的前端框架一般都采取换一个新Selector的方式对此进行处理,屏蔽掉了JDK5/6的问题,但对于此问题来讲,还是尽量将JDK的版本更新到最新,或者使用NIO框架如Netty,Grizzly等进行研发,以免出更多的问题。

 epoll bug CPU空轮询

SUN在解决该BUG的问题上不给力,只能从NIO框架层面进行问题规避,下面我们看下Netty是如何解决该问题的。

Netty的解决策略:

1) 根据该BUG的特征,首先侦测该BUG是否发生;

2) 将问题Selector上注册的Channel转移到新建的Selector上;

3) 老的问题Selector关闭,使用新建的Selector替换。

下面具体看下代码,首先检测是否发生了该BUG:

图2-27 epoll bug 检测

一旦检测发生该BUG,则重建Selector,代码如下:

图2-28 重建Selector

重建完成之后,替换老的Selector,代码如下:

图2-29 替换Selector

大量生产系统的运行表明,Netty的规避策略可以解决epoll bug 导致的IO线程CPU死循环问题。

netty的解决代码在package io.netty.channel.nio.nioEventLoop这个类下面。

Netty : 臭名昭著的JDK的NIO bug(空轮询bug) 1.美图 2.概述 在搞这个问题的时候 Netty:Netty不断打开文件的BUG 一直找不到原因,然后偶然想了一下是不是netty的空轮询bug,后来查了一下真的是,第一感觉居然是,我草,我草,好兴奋,太他妈刺激了,我居然遇到了传说中的bug,哈哈哈哈,容我笑一会。 在 李林峰的<Netty权威指南>,第2.6.1章写到不使用JDK原生NIO框架的原因是JDK存在epoll bu... 阅读详情

相关推荐

面试题趣谈:Netty如何处理NIO底层epoll空轮询bug?

你了解Netty的NIO epoll空轮询bug问题吗? 能否解释一下这个问题的成因和Netty是如何解决的?这个问题的成因是NIO底层epoll实现存在缺陷,它会频繁空轮询所有连接,即使没有新事件发生也会遍历所有连接。这会导致CPU使用率飙升到100%。Netty对这个问题进行了识别和处理。当它检测到Selector出现空轮询时,会立即创建一个新的Selector,然后将旧Selector上的SocketChannel重新注册到新Selector,最后关闭旧的Selector释放资源。

Gemini的博客 467

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

原文链接:应用服务器中对JDK的epoll空转bug的处理 前面讲到了epoll的一些机制,与select和poll等传统古老的IO多路复用机制的一些区别,这些区别实质可以总结为一句话, 就是epoll将重要的基于事件的fd集合放在了内核中来完成,因为内核是高效的,所以很多关于fd事件监听集合的操作也是高效的, 不方便的就是,因为在内核中,所以我们需要通过系统调用来调用关于fd操作集合,而不...

weixin_30624825的博客 554

【Java硬核知识:IO/NIO核心原理与性能压榨】Selector空轮询Bug:Netty是如何彻底解决的?

摘要:本文围绕 Java NIO 中 Selector 空轮询 Bug 展开,先回顾 NIO 基础与 Selector 工作原理,剖析空轮询触发条件,包括网络、系统、并发及 JDK 版本等因素。接着阐述 Netty 的 rebuildSelector 策略,通过检测空轮询后重建 Selector 解决问题,并分析其优缺点。同时介绍 select、poll 和 epoll 原理,说明 Java 中使用 epoll 的方法与优势。最后通过实操案例,展示基于 Netty 和 epoll 构建高性能网络服务器的过程

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1249

解决epoll产生过多EPOLLOUT事件导致cpu升高

当socket的缓冲区不满的时候,就会产生EPOLLOUT事件,但是通常情况下,应用层缓存并未准备好,这会导致epoll所在线程不断检测应用层缓存是否就绪,进而导致cpu高,一般情况下,解决消费者生产者速度不协调的通用办法是通过增加两个条件变量来解决,通过应用层缓存的非空和非满两个状态,来控制线程的休眠与运行,但epoll如果是使用单线程的反应器模式,就无法使用该方法了,我们可以通过另外一种方法来解决cpu高的问题,即: 如果epoll如果检测到缓存为空,那么就将该socket...

Nucleusx的专栏 1694

ArcMap安装与配置全攻略:从下载到实战应用

本文提供了ArcMap 10.4.1从系统准备、详细安装到破解激活的完整指南,并包含首次启动的界面介绍与一个实战GIS分析项目。针对初学者,文章强调了在ArcGIS Pro成为趋势的当下,学习经典ArcMap对于理解核心概念和兼容现有工作流仍有重要价值,帮助用户避开安装常见陷阱,快速上手实战应用。

weixin_29200741的博客 335

匈牙利算法解决指派问题清晰流程

匈牙利算法解决指派问题清晰流程 百度词条上,指派问题(Assignment problem)是这么定义的:在满足特定指派要求条件下,使指派方案总体效果最佳。如:有若干项工作需要分配给若干人(或部门)来完成;有若干项合同需要选择若干个投标者来承包:有若干班级需要安排在若干教室里上课等。   一、做减法(归约): 行归约:每行元素减去该行最小元素。 列归约:每行元素减去该行最小元素。

siss0siss的博客 6万+

那些年遇到的坑---EPOLL(cpu100%/卡死)

那些年遇到的坑—EPOLL(cpu100%/卡死) 最近在定位BUG时发现了这么一个问题 程序跑的设备上4个CPU只有一个CPU是跑满的状态,其他CPU的占用率都非常低,且此设备上几乎无业务。 通过火焰图定位是哪个模块出现问题之后,通过pstack 看看有问题的这个进程在干什么 pstack pid #0 0x00007fbea3424d43 in epoll_wait () from /lib64/libc.so.6 通过pstack 可以看到,有大量的系统调用sys_epoll_wait占用了CPU

vegeta852的博客 5388

把对讲门铃(控制底楼铁门)接入米家服务器

今天讲个跟SDR或者无人机无关的东西,技术含量不高,但是方便了我的生活。 现在家门有智能锁,汽车也可以远程解锁发动,NFC门禁也可以用某些手机复制,唯独楼下的铁门,必须用老式对讲门铃控制。 也就是说其它钥匙都可以不带,就剩这个钥匙还必须随身携带。 另外有时候人不在家,不能开楼下铁门,快递员也没法把东西送上楼。 ......

老邵的开源世界 6549

NIO中存在的bug—epoll空轮询

IO&NIO介绍 IO读取 NIO读取 NIO中epoll空轮询表现 public static void main(String[] args) { Selector selector = Selector.open(); System.out.println(selector.isOpen()); ServerS...

小弟_liao的博客 788

HTML5期末大作业:关于家乡介绍的HTML网页设计——郑州美景HTML+CSS(5页) 学生DW家乡介绍网页设计作业成品 web课程设计网页规划与设计

HTML5期末大作业:我的家乡——郑州美景HTML+CSS(5页) 学生DW网页设计作业成品 web课程设计网页规划与设计 计算机毕设网页设计源码 常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 明星、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他 等网页设计题目, A+水平作业, 可满足大学生网页大作业网页设计需求, 喜

qq_365392777 1万+

基于Simulink的鲸鱼优化算法(WOA)MPPT仿真

摘要:本文介绍了基于Simulink的鲸鱼优化算法(WOA)在光伏MPPT控制中的应用。WOA模拟座头鲸的"气泡网捕食策略",通过包围猎物、螺旋收缩和随机搜索三阶段动态平衡全局探索与局部开发能力,有效解决局部阴影导致的多峰P-V曲线问题。文章详细讲解了WOA-MPPT的Simulink建模过程,包括多峰光伏阵列建模、WOA控制器实现和Boost变换器控制。仿真结果显示,在三种典型工况下,WOA-MPPT的追踪效率>99.3%,动态响应时间<0.15s,性能优于传统算法。最后提出了混合WO

amy_mhd的博客 71

java epoll bug_NIO的epoll空轮询bug

JDK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该BUG发生概率降低了一些而已,它并没有被根本解决。该BUG以及与该BUG相关的问题单可以参见以下链接内容。Selector BUG出现的原因若Selector的轮询结果为空,也没...

weixin_31776191的博客 2046

风机叶片小规模振动监测数据集--读取测试

ETH风电叶片缺陷数据集–读取测试 数据简介 提示:这里可以添加本文要记录的大概内容: 结构健康监测是保障重要机电设备、建筑设施健康的重要技术手段。 一、lvm_read包安装 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务

cnjs1994的博客 2850

Netty巧妙的规避了JDK在linux中NIO的epoll的空轮询Bug

一、NIO的空轮询bug描述 JDK1.5开始引入了epoll基于事件响应机制来优化NIO。相较于select和poll机制来说,epoll机制将事件处理交给了操作系统内核(操作系统硬中断)来处理,优化了elect和poll模型的无效遍历问题。 但是JDK中epoll的实现却是有漏洞的,其中最有名的就是NIO空轮询bug(该bug只存在于Linux,因为Linux中NIO底层是使用epoll实现的,而Windows不是)。 理论上无客户端连接时Selector.select() 方法会阻塞,但空轮询b.

HD243608836的博客 1903

路径规划 | 图解粒子群(PSO)算法(附ROS C++仿真)

粒子群算法(PSO)的基本思想是模拟鸟群觅食机制,将鸟类的觅食方向分为自我认知部分和社会部分,个体自主探索群体周围空间的同时,也随着群体的主流方向前进,不断逼近最优目标。本文详解PSO算法基本概念,并给出ROS C++实现加深理解

FRIGIDWINTER的博客 2614

云计算 | 期末梳理(上)

2024云计算回忆版 && 复盘向梳理

知识库搭建ing 2230

java nio epoll bug_Java nio 空轮询bug到底是什么

编者注:Java nio 空轮询bug也就是Java nio在Linux系统下的epoll空轮询问题。epoll机制是Linux下一种高效的IO复用方式,相较于select和poll机制来说。其高效的原因是将基于事件的fd放到内核中来完成,在内核中基于红黑树+链表数据结构来实现,链表存放有事件发生的fd集合,然后在调用epoll_wait时返回给应用程序,由应用程序来处理这些fd事件。使用IO复用...

weixin_39621695的博客 152

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

nio epoll空轮询bug与netty的解决方案

epoll空轮询

weixin_40857858的博客 585

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

java socket通信 解决jdk自带的 nio epoll 空轮询bug (各种nio框架的解决方案)

转自:https://www.cnblogs.com/JAYIT/p/8241634.html   JDK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该BUG发生概率降低了一些而已,它并没有被根本解决。该BUG以及与该BUG相...

hemeinvyiqiluoben的专栏 3870

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Netty 是如何解决 NIO epoll 空轮询 Bug ?

JDK NIO epoll 空轮询 Bug 一般 selector.select() 是阻塞的,只有被监听的 FD(文件描述符) 有读写操作时,才会被唤醒。 但在这个 bug 中,没有任何 FD 读写操作时 select() 依然会被唤醒。 代码案例 Netty 是如何解决 NIO epoll 空轮询 Bug ? 对 selector 的 select() 操作周期进行统计,每完成一次 select() 操作进行一次计数; 若在某个周期内连续发生 N 次空轮询,则触发 epoll 死循环 bug; 这种情

晨猫 725

【Netty基础】Netty的高性能及NIO的epoll空轮询bug

Selector BUG出现的原因若Selector的轮询结果为空,也没有wakeup或新消息处理,则发生空轮询,CPU使用率100%,Netty的解决办法 对Selector的select操作周期进行统计,每完成一次空的select操作进行一次计数, 若在某个周期内连续发生N次空轮询,则触发了epoll死循环bug。 重建Selector,判断是否是其他线程发起的重建请求,若不是则将原Socket

白夜行 2万+

DK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。...

JDK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该BUG发生概率降低了一些而已,它并没有被根本解决。该BUG以及与该BUG相关的问题单可以参见以下链接内容。 https://bugs.java.com/bugdatabas...

weixin_30852419的博客 1220

java epoll bug_Java nio 空轮询bug到底是什么

编者注:Java nio 空轮询bug也就是Java nio在Linux系统下的epoll空轮询问题。epoll机制是Linux下一种高效的IO复用方式,相较于select和poll机制来说。其高效的原因是将基于事件的fd放到内核中来完成,在内核中基于红黑树+链表数据结构来实现,链表存放有事件发生的fd集合,然后在调用epoll_wait时返回给应用程序,由应用程序来处理这些fd事件。使用IO复用...

weixin_35959694的博客 352
上一篇: Redis发布带有“流式”数据类型的5.0版本
下一篇: MyBatis拦截器原理探究
god_love_hlq_xff
博客等级 码龄11年 27粉丝 37原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值