`

Java NIO epoll 空转问题 + Netty 解决方法

    博客分类:
  • Java
阅读更多

在 Java NIO 编程实践中,很多人都会选择 Netty 作为基础框架,而不是直接用 JDK 原生的 NIO API。
因为 JDK 原生的 NIO 框架内容过于繁杂、学习成本高、补齐可靠性的工作量和难度都很大、还有一些bug。
其中一个著名的bug就是 epoll Selector 空转问题。

 

相关Bug单

 

问题表象

示例代码(仅做示例,未考虑异常处理):

while (true) {
  selector.select();

  Iterator it = selector.selectedKeys().iterator();
  while (it.hasNext()) {
    SelectionKey key = (SelectionKey) it.next();
    int ops = key.interestOps();

    if (0 != (ops & SelectionKey.OP_ACCEPT)) {
      // 处理新连接
    }

    if (0 != (ops & SelectionKey.OP_READ)) {
      // 读取消息
    }

    it.remove();
  }
}

 

在使用 JDK NIO 框架时我们通常会采用上述模式的代码来处理客户端请求。
执行 Selector.select() 方法时会一直阻塞,直到有 channel 就绪。
但是在实践中,可能:

  1. 没有 channel 就绪,该方法也会返回。(违反原来的阻塞行为设计)
  2. 因为没有 channel 就绪,所以内部的 while 循环不会执行。
  3. 继而不断执行外部的 while (true) 循环。
  4. 上述步骤不断重复就形成空转轮询,CPU占用率达到100%,无法执行其它任务,最终程序崩溃。

 

问题原因

在部分 Linux 内核中,在 poll 或 epoll 一个已连接的socket,且请求事件掩码为0 的情况下,如果连接被突然中断,那么 poll/epoll 会被唤醒,相应事件标识为 POLLHUP(或 POLLERR)。
继而Selector被唤醒,且 interest set 为0,没有相应的 Channel,select() 返回值也是0。

JDK-6403933 写道
This is an issue with poll (and epoll) on Linux. If a file descriptor for a connected socket is polled with a request event mask of 0, and if the connection is abruptly terminated (RST) then the poll wakes up with the POLLHUP (and maybe POLLERR) bit set in the returned event set. The implication of this behaviour is that Selector will wakeup and as the interest set for the SocketChannel is 0 it means there aren't any selected events and the select method returns 0.

 

Netty 的解决方法

Netty 的解决方式是 重建一个新的 Selector,替代原来出错的 Selector
 

大致方法如下:

  • 在一个 select 周期中,统计 空select 操作 的次数
  • 当 空select 操作次数累计到阈值时,就认为触发了 epoll空转 bug。
  • 然后重建 Selector:
    新建一个 Selector;
    将 原Selector 上的 Channel 注册到 新Selector;
    关闭 原Selector。

上述判定阈值默认为 512。可通过JVM系统变量设置(io.netty.selectorAutoRebuildThreshold)。
可在 NioEventLoop 类中查看相关代码。


 

思考

可能因为此问题的根源在于底层Linux内核行为的不一致,所以Java官方一开始将其抛给了操作系统实现方,导致该bug存在了很久。也许Java官方相关决策者认为,此类bug最恰当的修复方案应该在底层操作系统,而不是由上层Java去糊一层,因为JDK有自己的设计原则,并不是无脑做得越多越好。
 

其实这种分层分治的思维方式是非常令人欣赏的。很多优秀产品的缔造者内心都秉持这个原则。
如,Robot Framework 的负责人 Pekka Klärck 认为 IronPython 处理全角空格的不同方式应该由 IronPython 实现者去修改,而不是让 Robot Framework 在上面糊一层:
Support for 'IDEOGRAPHIC SPACE' (U+3000) in test data on IronPython
 

反观很多产品经理,毫无原则,只会做附庸,客户说啥就是啥,领导说啥就是啥,自己也没有足够的知识和经验储备,尽出些拙劣的程序,根本不能称为产品。真的是“人人都是产品经理”。

 

  • 大小: 15 KB
分享到:
评论

相关推荐

    NIO+Netty5视频教程与Netty源码剖析视频教程

    《NIO+Netty5视频教程与Netty源码剖析视频教程》是一份全面解析网络编程框架Netty的教育资源,旨在帮助学习者深入理解和应用NIO(非阻塞I/O)以及Netty5的核心技术。该教程分为两个主要部分,分别针对理论分析和实战...

    springboot+netty+websocket+redis

    Netty底层基于NIO(非阻塞I/O)模型,提高了网络通信的性能。 ### 3. WebSocket - 实时消息传输 WebSocket是一种在单个TCP连接上进行全双工通信的协议,允许服务器主动推送数据给客户端,无需频繁的轮询。在Spring ...

    nio+bio+netty+fx.zip

    项目中的`nio+bio+netty+fx`可能包含以下文件: - `BioChatServer.java`: 实现基于BIO的服务器端代码。 - `BioChatClient.java`: 实现基于BIO的客户端代码。 - `NioChatServer.java`: 实现基于NIO的服务器端代码。 -...

    【项目实战】Netty源码剖析&NIO;+Netty5各种RPC架构实战演练三部曲视频教程(未加密)

    Netty是一款基于Java NIO的高性能服务器端编程框架,用于快速开发可维护的网络应用程序。它简化了网络编程的复杂性,使开发者能够更加专注于业务逻辑的实现。Netty提供了事件驱动模型、异步处理能力以及丰富的API...

    springboot2.3+modbusTcp协议+netty高性能物联网服务

    Netty NIO high performance高性能;Modbus Function sync/aync 同步/异步非阻塞;Modbus IoT Data Connector Supports工业物联网平台IoT支持。

    springboot+netty实现mqtt协议的broken

    标题"springboot+netty实现mqtt协议的broken"可能意味着这个项目旨在解决Spring Boot与Netty集成时可能出现的问题,或者是一个关于如何处理MQTT连接中断的教程。在实际应用中,MQTT连接可能会因为各种原因断开,例如...

    Spring Boot + Netty 实现温湿度采集的展示

    6. **监控与管理**:Spring Boot Actuator提供健康检查、指标、审计跟踪等功能,帮助开发者监控系统的运行状态,及时发现并解决问题。 7. **实时性**:为了实现实时显示,系统可能会采用WebSocket或其他长连接技术...

    Java NIO 中英文版 + Pro Java 7 NIO.2

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java平台中用于高效处理I/O操作的重要框架。它在Java 1.4版本中被引入,替代了传统的IO模型,提供了更高级别的I/O操作机制,以适应并发编程的需求...

    java nio im(server+client)

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种新的I/O模型,相对于传统的BIO( Blocking I/O)模型,NIO在处理高并发、大数据量的网络应用时表现出更高的效率和...

    NIO+Netty5视频教程2018

    【标题】"NIO+Netty5视频教程2018"揭示了两个核心主题:Netty框架的源码分析和基于NIO的RPC架构实战。这个教程旨在帮助Java开发者深入理解和应用NIO(Non-blocking Input/Output)技术以及Netty网络框架,尤其在构建...

    Java整合springboot2.3+modbusTcp协议+netty高性能物联网服务源码

    Java整合springboot2.3+modbusTcp协议+netty高性能物联网服务源码 1、Netty NIO high performance高性能. 2、Modbus Function sync/aync 同步/异步非阻塞。 3、Modbus IoT Data Connector Supports工业物联网平台IoT...

    spring boot +maven+ netty4+protostuff+zookeeper实现一个轻量级RPC框架

    Netty:它使 NIO 编程更加容易,屏蔽了 Java 底层的 NIO 细节。 Protostuff:它基于 Protobuf 序列化框架,面向 POJO,无需编写 .proto 文件。 ZooKeeper:提供服务注册与发现功能,开发分布式系统的必备选择,同时...

    Java高级课程(nginx+redis+zookeeper+activemq+storm+dubbo+netty+jvm+并发编程锁+项目实战)

    Java高级互联网架构师系统培训班课程Java高级互联网架构师系统培训班课程Java高级互联网架构师系统培训班课程

    springboot+netty+mybatis+sqlserver

    在Java生态系统中,Netty因其高效的NIO模型而被广泛应用于高并发的TCP/UDP网络通信,如游戏服务器、聊天服务器等。在这里,Netty可能作为底层通信层,负责处理客户端的连接请求和数据传输。 MyBatis是一个优秀的...

    springboot+netty开发简易式游戏源码

    1. **NIO基础**:Netty基于Java NIO,允许非阻塞的I/O操作,提高了并发处理能力。 2. **Channel**:Netty的I/O操作都围绕着Channel进行,它可以读写数据并管理连接状态。 3. **EventLoop**:每个Channel都与一个...

    java NIO入门(中英+代码)

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种I/O模型,旨在提供一种更高效、更具控制力的I/O操作方式。与传统的 Blocking I/O(同步阻塞I/O)相比,NIO的核心特点...

    springboot+netty+webSocket实现在线聊天.zip

    Netty的ByteBuf替代了Java NIO中的ByteBuffer,提供了更方便的数据操作,而且Netty的ChannelHandler可以灵活处理各种网络事件。 **WebSocket** WebSocket是一种在客户端和服务器之间建立长连接的协议,支持双向通信...

    Netty面试题 +Netty综合面试题整合

    - **NIO 和 EPOLL**:Netty 支持基于 Java NIO 和 Linux EPOLL(用于提高性能)的两种选择。 3. **Netty 的零拷贝**: - **FileRegion** 和 **DirectBuffer**:通过减少数据在用户空间和内核空间之间的复制,提高...

    android+netty 的demo

    通过阅读"jan_s"的博客,你可能能找到更多关于如何解决这些问题的具体实现细节。这个示例对于理解Android环境下如何使用Netty,以及如何优化以适应Android平台的限制,都是非常有价值的参考资料。

    springboot+netty.rar

    Netty是一个Java NIO(非阻塞I/O)框架,用于构建高性能的服务器和客户端。Netty的核心在于它的EventLoop和ChannelHandler机制,前者负责事件的调度和执行,后者处理实际的业务逻辑。Netty提供了一种灵活的方式来...

Global site tag (gtag.js) - Google Analytics