Netty「源码阅读」之怎么解决 Java 的 epoll 空轮询 bug

简介: Netty「源码阅读」之怎么解决 Java 的 epoll 空轮询 bug

前言

Java NIO中有一个著名的 bug epoll, 这个 bug 会导致Reactor线程被唤醒, 进行空轮询, 最终COU 100%爆满, 那么Netty是怎么解决epollbug 的呢

在上篇文章中我们有说过, NioEventLoop.run()方法是基于Selector的轮询方法, 在方法内部实现了死循环去获取网络IO事件并执行

也是在该方法中Netty巧妙地解决了epollbug, 接下来让我们定位到该方法


Netty 解决 epoll

在这个方法中, 我将重点的步骤进行了标注, 先说流程, 然后在进行针对性的讲解

  • 初始化selectCnt 这个变量是解决epoll的关键
  • 定义变量strategy, 他是int类型, 默认是0
  • 执行selectStrategy.calculateStrategy()方法获取当前网络IO事件数量
  • 根据strategy来执行不同的操作, 这个后面贴详细代码讲一下
  • 这个时候我们的变量selectCnt++
  • 我们会对当前执行的任务和strategy进行判断, 对selectCnt进行归零操作
  • 否则, 我们会对执行方法unexpectedSelectorWakeup()selectCnt进行边界值判断

网络异常,图片无法展示
|

Switch

switch中, 一共case了三个常量

  • SelectStrategy.CONTINUE: 继续, 直接跳过, 这里不做讲解
  • SelectStrategy.BUSY_WAIT: NIO不支持 BUSY_WIAT, 所以和 SELECT 是一样的
  • SelectStrategy.SELECT: 判断当前 IO事件 是否就绪, 如果没有就绪就让线程休息, 不进行唤醒

网络异常,图片无法展示
|

SelectStrategy.SELECT

具体判断线程是否要苏醒的地方是下面两个红框

网络异常,图片无法展示
|

unexpectedSelectorWakeup()方法

实际上解决空轮询问题的地方就是在这里

网络异常,图片无法展示
|

在这个方法中我们可以看到, 方法返回值是判断selectCnt是否大于静态变量SELECTOR_AUTO_REBUILD_THRESHOLD, 那么我们看一下这个变量的赋值过程

网络异常,图片无法展示
|

跟着序号看起, 先是定义了变量, 然后将selectorAutoRebuildThreshold赋值于SELECTOR_AUTO_REBUILD_THRESHOLD, 可以看到执行了SystemPropertyUtil.getInt方法, 这个方法是获取你配置文件中的值, 如果你的配置文件中没有进行配置, 那么就使用后面的默认值512

这也就是为什么, 我们经常看到说: 当Netty空轮询阈值是512

假设我们的selectCnt已经达到了512, 还会执行一个方法rebuildSelector();顾名思义, 重建Selector

网络异常,图片无法展示
|

这个方法的作用是将当前这个发生空轮训的selector上的selectedKeys挪到新建的selector选择器上,从而完美解决空轮训的问题

然后我们的unexpectedSelectorWakeup返回true, 回到之前的run()方法中可以看到, 作者将selectCnt重新赋值为了0, 所以作者也不算是解决了这个bug, 但是巧妙的将其绕过了

网络异常,图片无法展示
|

总结

总结就简单写写, 初始化变量selectCnt, 每次轮询进行++操作, 后面会将其进行归零, 如果没有归零selectCnt, 会执行unexpectedSelectorWakeup()方法, 如果达到了512, 会进行selector重建



目录
相关文章
|
1月前
|
存储 小程序 Java
热门小程序源码合集:微信抖音小程序源码支持PHP/Java/uni-app完整项目实践指南
小程序已成为企业获客与开发者创业的重要载体。本文详解PHP、Java、uni-app三大技术栈在电商、工具、服务类小程序中的源码应用,提供从开发到部署的全流程指南,并分享选型避坑与商业化落地策略,助力开发者高效构建稳定可扩展项目。
|
4月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
213 3
|
5月前
|
算法 Java 容器
Netty源码—4.客户端接入流程
本文主要介绍了关于Netty客户端连接接入问题整理、Reactor线程模型和服务端启动流程、Netty新连接接入的整体处理逻辑、新连接接入之检测新连接、新连接接入之创建NioSocketChannel、新连接接入之绑定NioEventLoop线程、新连接接入之注册Selector和注册读事件、注册Reactor线程总结、新连接接入总结
|
5月前
|
安全 Java 调度
Netty源码—3.Reactor线程模型二
本文主要介绍了NioEventLoop的执行总体框架、Reactor线程执行一次事件轮询、Reactor线程处理产生IO事件的Channel、Reactor线程处理任务队列之添加任务、Reactor线程处理任务队列之执行任务、NioEventLoop总结。
|
5月前
|
安全 Java
Netty源码—2.Reactor线程模型一
本文主要介绍了关于NioEventLoop的问题整理、理解Reactor线程模型主要分三部分、NioEventLoop的创建和NioEventLoop的启动。
|
5月前
|
编解码 安全 Java
Netty源码—1.服务端启动流程
本文主要介绍了服务端启动整体流程及关键方法、服务端启动的核心步骤、创建服务端Channel的源码、初始化服务端Channel的源码、注册服务端Channel的源码、绑定服务端端口的源码、服务端启动流程源码总结。
|
5月前
|
JavaScript Java 关系型数据库
家政系统源码,java版本
这是一款基于SpringBoot后端框架、MySQL数据库及Uniapp移动端开发的家政预约上门服务系统。
173 6
家政系统源码,java版本
|
5月前
|
供应链 JavaScript 前端开发
Java基于SaaS模式多租户ERP系统源码
ERP,全称 Enterprise Resource Planning 即企业资源计划。是一种集成化的管理软件系统,它通过信息技术手段,将企业的各个业务流程和资源管理进行整合,以提高企业的运营效率和管理水平,它是一种先进的企业管理理念和信息化管理系统。 适用于小微企业的 SaaS模式多租户ERP管理系统, 采用最新的技术栈开发, 让企业简单上云。专注于小微企业的应用需求,如企业基本的进销存、询价,报价, 采购、销售、MRP生产制造、品质管理、仓库库存管理、财务应收付款, OA办公单据、CRM等。
319 23
|
6月前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
455 7
|
6月前
|
Java 关系型数据库 MySQL
Java汽车租赁系统源码(含数据库脚本)
Java汽车租赁系统源码(含数据库脚本)
123 4