Netty源码-04-Selector
Netty对Selector的优化体现在两个方面:
- 数据结构替换,数组替换hash表,轮询时直接寻址,提高查询效率。
- 基于Linux系统epoll封装的Selector可能存存在空轮询风险,尽量减少空轮询出现带来的负面影响。
一 数据结构
每个IO线程都绑定了唯一的复用器,因此Selector的初始化时机是在创建NioEventLoop时。
java
1 |
|
java
1 |
|
声明了一个数据结构用于存放Selector,对于Netty框架而言,不在主观上强制使用优化策略,因此需要留存最终的实现方案selector,优化版的实现需要依赖Jdk原生的实现,相当于unwrappedSelector时临时存储而已。
因此只要关注selector的实现就行:
java
1 |
|
java
1 |
|
实现也很简单,就是将Jdk原生的实现Selector中的两个阈selectedKeys和publicSelectedKeys这两个hash表实现换成数组实现。
二 空轮询
java
1 |
|
在NioEventLoop线程启动之后,线程轮询于IO任务和非IO任务之间,阻塞点是IO多路复用器的select操作。
但是Jdk对于EPoll多路复用的封装有缺陷,可能发生本该阻塞等待的线程被唤醒,publicSelectedKeys中并没有IO事件,也就是发生了一次空select操作,一旦整个线程轮询模型处于空轮询中,一直占用CPU导致资源浪费。
Netty并没有重新封装EPoll的实现,还是使用的Jdk方案,只是加了一层预警式防御。也就是说空转仍然可能会出现,但是不让空转线程一直占用CPU,当空转次数达到一定阈值时,Netty将其判定为发生了空转,需要防御处理,手段就是重新构建Selector。
java
1 |
|
重建Selector也是由NioEventLoop线程完成:
java
1 |
|
java
1 |
|
Netty源码-04-Selector
https://bannirui.github.io/2023/03/06/Netty源码-04-Selector/