跳到正文
Elaine Blog
返回

Netty 线程模型与任务调度:不要阻塞 EventLoop

网络与 I/O

Netty 的高吞吐来自少量 EventLoop 快速推进大量连接,不是因为它能让慢业务自动变快。只要一个处理器阻塞,归属同一 EventLoop 的其他连接都会增加延迟。

Table of contents

Open Table of contents

Channel 为什么固定在一个 EventLoop

同一 Channel 的事件由固定 EventLoop 串行处理,处理器可以减少连接内状态的锁竞争。跨线程调用 channel.writeAndFlush 时,Netty 会把实际操作安排回所属 EventLoop。

EventLoop 通常轮流处理 I/O 事件和任务队列。一个任务运行太久,定时任务、读取和写完成通知都会延后。因此“线程没有死锁”并不代表事件循环健康。

哪些工作必须卸载

任务卸载样例下载把慢任务交给单独执行器:

mvn -Dtest=NetworkServerLabTest#offloadsSlowWork test

样例使用虚拟线程便于表达阻塞任务,但生产环境仍必须限制并发,因为数据库连接、远端配额和内存不会随虚拟线程增加。

卸载不是无限提交

执行器要有明确所有者、并发上限、排队上限、拒绝策略和关闭流程。请求离开 EventLoop 前记录截止时间;轮到执行时如果截止时间已过,直接取消,不再消耗下游资源。

响应完成后还要检查 Channel 是否仍然活跃、请求是否已取消。多个请求允许乱序响应时用请求 ID 关联;协议要求顺序时必须显式排序,不能依赖任务恰好按提交顺序结束。

测量事件循环积压

平均接口耗时会掩盖短暂卡顿。至少观测:

指标说明
事件循环延迟定时任务实际执行时间减计划时间
待执行任务数是否持续积压
Handler 执行分位数哪个处理阶段变慢
Channel 不可写时间出站是否堵塞
工作执行器队列与拒绝卸载层是否饱和

压测时同时制造慢下游、半包、慢客户端和连接关闭,观察系统是否有界退化。只用本机持续发送小包,无法证明生产稳定性。

线程模型的选择

短小非阻塞协议处理留在 EventLoop;可控 CPU 任务交给固定大小池;大量阻塞 I/O 可评估有并发门控的虚拟线程。选择依据是工作性质和下游容量, 不是“线程越少越先进”或“虚拟线程越多越快”。

下一步

阅读Netty 内存池、引用计数与泄漏排查,理解高吞吐缓冲区怎样安全回收。


分享这篇文章:

上一篇
编解码、粘包拆包与背压
下一篇
Netty 内存池、引用计数与泄漏排查