一篇写给所有 Netty 玩家的 “从源码到性能” 深度笔记
目录
- 前言
- EventLoopGroup 家族
- NioEventLoopGroup 架构
- 创建与配置
- 生命周期源码走读
- 线程模型与调度
- 性能调优实战
- 常见问题 FAQ
- 总结
前言
在 Netty 中,NioEventLoopGroup 既是 线程池,又是 Selector 管理者。
理解它 = 理解 Netty 高并发的一半。
EventLoopGroup 家族
| 实现类 |
适用场景 |
底层 |
NioEventLoopGroup |
通用 NIO |
Selector + Thread |
EpollEventLoopGroup |
Linux 高并发 |
epoll |
KQueueEventLoopGroup |
macOS/BSD |
kqueue |
NioEventLoopGroup 架构
NioEventLoopGroup
├─ NioEventLoop[0] -> Thread-0 + Selector-0
├─ NioEventLoop[1] -> Thread-1 + Selector-1
└─ ...
- NioEventLoop = 单线程 + 单 Selector
- Boss 组 只负责 accept
- Worker 组 负责 read/write
创建与配置
| 参数 |
默认值 |
建议 |
nThreads |
0 → CPU*2 |
显式指定 |
executor |
null |
自定义线程工厂 |
ioRatio |
50 |
业务 vs I/O 时间片 |
// 最常用写法
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup(0); // 自动
生命周期源码走读
// 1. 构造
public NioEventLoopGroup(int nThreads, Executor executor) {
super(nThreads, executor, SelectorProvider.provider());
}
// 2. newChild 创建 NioEventLoop
@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
DefaultSelectStrategyFactory.INSTANCE);
}
线程模型与调度
- 注册 Channel:
eventLoop.execute(() -> register(...))
- I/O 事件:
select() → processSelectedKeys()
- 任务队列:
SingleThreadEventExecutor.taskQueue
// 提交任务到同一条线程
channel.eventLoop().execute(() -> doBusiness());
性能调优实战
| 场景 |
配置 |
| 万连接网关 |
worker = new NioEventLoopGroup(0) |
| CPU 密集 |
业务线程池 + ioRatio=10 |
| Linux |
-Dio.netty.transport.noNative=false 启用 epoll |
常见问题 FAQ
| 问题 |
解决 |
| “too many open files” |
ulimit -n 65536 |
| 空轮询 100% CPU |
升级 Netty ≥ 4.1.50 |
| 业务阻塞 |
转业务线程池 |
总结
- 1 张图:NioEventLoopGroup = 线程池 + Selector
- 2 句话:创建 → 注册 → select → 处理
- 3 口诀:线程数=CPU*2、耗时任务外移、优雅关闭必调
掌握 NioEventLoopGroup,你就真正跨入了 Netty 高并发的大门!