在 Java NIO 编程实践中,很多人都会选择 Netty 作为基础框架,而不是直接用 JDK 原生的 NIO API。
因为 JDK 原生的 NIO 框架内容过于繁杂、学习成本高、补齐可靠性的工作量和难度都很大、还有一些bug。
其中一个著名的bug就是 epoll Selector 空转问题。
相关Bug单
- 《JDK-6670302 : (se) NIO selector wakes up with 0 selected keys infinitely [lnx 2.4]》
- 《JDK-6403933 : (se) Selector doesn't block on Selector.select(timeout) (lnx)》
- 《JDK-2147719 : (se) Selector doesn't block on Selector.select(timeout) (lnx)》
问题表象
示例代码(仅做示例,未考虑异常处理):
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 就绪。
但是在实践中,可能:
- 没有 channel 就绪,该方法也会返回。(违反原来的阻塞行为设计)
- 因为没有 channel 就绪,所以内部的 while 循环不会执行。
- 继而不断执行外部的 while (true) 循环。
- 上述步骤不断重复就形成空转轮询,CPU占用率达到100%,无法执行其它任务,最终程序崩溃。
问题原因
在部分 Linux 内核中,在 poll 或 epoll 一个已连接的socket,且请求事件掩码为0 的情况下,如果连接被突然中断,那么 poll/epoll 会被唤醒,相应事件标识为 POLLHUP(或 POLLERR)。
继而Selector被唤醒,且 interest set 为0,没有相应的 Channel,select() 返回值也是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》
反观很多产品经理,毫无原则,只会做附庸,客户说啥就是啥,领导说啥就是啥,自己也没有足够的知识和经验储备,尽出些拙劣的程序,根本不能称为产品。真的是“人人都是产品经理”。
相关推荐
《NIO+Netty5视频教程与Netty源码剖析视频教程》是一份全面解析网络编程框架Netty的教育资源,旨在帮助学习者深入理解和应用NIO(非阻塞I/O)以及Netty5的核心技术。该教程分为两个主要部分,分别针对理论分析和实战...
Netty底层基于NIO(非阻塞I/O)模型,提高了网络通信的性能。 ### 3. WebSocket - 实时消息传输 WebSocket是一种在单个TCP连接上进行全双工通信的协议,允许服务器主动推送数据给客户端,无需频繁的轮询。在Spring ...
项目中的`nio+bio+netty+fx`可能包含以下文件: - `BioChatServer.java`: 实现基于BIO的服务器端代码。 - `BioChatClient.java`: 实现基于BIO的客户端代码。 - `NioChatServer.java`: 实现基于NIO的服务器端代码。 -...
Netty是一款基于Java NIO的高性能服务器端编程框架,用于快速开发可维护的网络应用程序。它简化了网络编程的复杂性,使开发者能够更加专注于业务逻辑的实现。Netty提供了事件驱动模型、异步处理能力以及丰富的API...
Netty NIO high performance高性能;Modbus Function sync/aync 同步/异步非阻塞;Modbus IoT Data Connector Supports工业物联网平台IoT支持。
标题"springboot+netty实现mqtt协议的broken"可能意味着这个项目旨在解决Spring Boot与Netty集成时可能出现的问题,或者是一个关于如何处理MQTT连接中断的教程。在实际应用中,MQTT连接可能会因为各种原因断开,例如...
6. **监控与管理**:Spring Boot Actuator提供健康检查、指标、审计跟踪等功能,帮助开发者监控系统的运行状态,及时发现并解决问题。 7. **实时性**:为了实现实时显示,系统可能会采用WebSocket或其他长连接技术...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java平台中用于高效处理I/O操作的重要框架。它在Java 1.4版本中被引入,替代了传统的IO模型,提供了更高级别的I/O操作机制,以适应并发编程的需求...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种新的I/O模型,相对于传统的BIO( Blocking I/O)模型,NIO在处理高并发、大数据量的网络应用时表现出更高的效率和...
【标题】"NIO+Netty5视频教程2018"揭示了两个核心主题:Netty框架的源码分析和基于NIO的RPC架构实战。这个教程旨在帮助Java开发者深入理解和应用NIO(Non-blocking Input/Output)技术以及Netty网络框架,尤其在构建...
Java整合springboot2.3+modbusTcp协议+netty高性能物联网服务源码 1、Netty NIO high performance高性能. 2、Modbus Function sync/aync 同步/异步非阻塞。 3、Modbus IoT Data Connector Supports工业物联网平台IoT...
Netty:它使 NIO 编程更加容易,屏蔽了 Java 底层的 NIO 细节。 Protostuff:它基于 Protobuf 序列化框架,面向 POJO,无需编写 .proto 文件。 ZooKeeper:提供服务注册与发现功能,开发分布式系统的必备选择,同时...
Java高级互联网架构师系统培训班课程Java高级互联网架构师系统培训班课程Java高级互联网架构师系统培训班课程
在Java生态系统中,Netty因其高效的NIO模型而被广泛应用于高并发的TCP/UDP网络通信,如游戏服务器、聊天服务器等。在这里,Netty可能作为底层通信层,负责处理客户端的连接请求和数据传输。 MyBatis是一个优秀的...
1. **NIO基础**:Netty基于Java NIO,允许非阻塞的I/O操作,提高了并发处理能力。 2. **Channel**:Netty的I/O操作都围绕着Channel进行,它可以读写数据并管理连接状态。 3. **EventLoop**:每个Channel都与一个...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种I/O模型,旨在提供一种更高效、更具控制力的I/O操作方式。与传统的 Blocking I/O(同步阻塞I/O)相比,NIO的核心特点...
Netty的ByteBuf替代了Java NIO中的ByteBuffer,提供了更方便的数据操作,而且Netty的ChannelHandler可以灵活处理各种网络事件。 **WebSocket** WebSocket是一种在客户端和服务器之间建立长连接的协议,支持双向通信...
- **NIO 和 EPOLL**:Netty 支持基于 Java NIO 和 Linux EPOLL(用于提高性能)的两种选择。 3. **Netty 的零拷贝**: - **FileRegion** 和 **DirectBuffer**:通过减少数据在用户空间和内核空间之间的复制,提高...
通过阅读"jan_s"的博客,你可能能找到更多关于如何解决这些问题的具体实现细节。这个示例对于理解Android环境下如何使用Netty,以及如何优化以适应Android平台的限制,都是非常有价值的参考资料。
Netty是一个Java NIO(非阻塞I/O)框架,用于构建高性能的服务器和客户端。Netty的核心在于它的EventLoop和ChannelHandler机制,前者负责事件的调度和执行,后者处理实际的业务逻辑。Netty提供了一种灵活的方式来...