831 字
约 2 分钟
11
S17-A03 · Netty 与网络编程模型

适用读者:想搞懂"为什么 Netty 能撑高并发"的人。
前置:S02-B09(IO 多路复用)、S04-J06(NIO)。
覆盖旧文:1846(240) 1088(108) 1089(84) 1090(87) 1092(95) 1093(69) 1094(99) 1095(76) 1096(75) 1097(87) 1091(93) 2627(204) 2319(44) 504(40) = 1,401 点。
覆盖扩展:E-S17-016(线程模型与粘包)。
上一篇:S17-A02 · 链路追踪与可观测性
下一篇:S17-X01 · 八股速查。


1. 一句话结论

Netty 快不是因为"某个黑科技",而是把四件事做到极致:事件循环(Reactor)、零拷贝、对象池、无锁化。

机制 作用
Reactor 线程模型 少量线程管大量连接(S02-B09)
零拷贝 减少内核/用户态复制
ByteBuf + 对象池 减少 GC 与内存分配
无锁化设计 减少竞争

2. 线程模型:Boss + Worker(E-S17-016)

BossGroup(1 线程):接收连接
WorkerGroup(N 线程):处理读写
        ↓
每个 Channel 绑定一个 EventLoop(单线程处理它的所有事件)

"为什么单线程处理一个连接":避免并发修改 Channel 状态——这正是它"无锁化"的来源。

判据:"业务处理耗时长吗?" 长 → 交给业务线程池,别堵 EventLoop(与 S05-B05 的"别堵线程池"同源)。


3. 零拷贝的两层含义(A-1092)

层 说明
OS 层 sendfile/mmap 减少复制(与 Kafka 同)
Netty 层 CompositeByteBuf/slice 避免内存拷贝

"零拷贝不是真的零次":是"减少不必要的 CPU 拷贝",DMA 复制仍存在。


4. ByteBuf 与对象池(A-1094/A-1095)

对比 JDK ByteBuffer Netty ByteBuf
读写指针 一个 position(要 flip) 两个指针(读/写独立)
动态扩容 不支持 ✅
池化 ❌ ✅(PooledByteBufAllocator)

"为什么池化重要":高并发下频繁分配/回收大 buffer → GC 压力(与 S05-J04 的 TLAB 优化同思路)。


5. 粘包与拆包(A-1090)

TCP 是字节流,没有消息边界(S02-B04 的核心结论)。Netty 提供解码器:

解码器 适用
FixedLengthFrameDecoder 定长
LineBasedFrameDecoder 换行分隔
LengthFieldBasedFrameDecoder 长度前缀(最常用)
DelimiterBasedFrameDecoder 自定义分隔符

判据:"协议里有长度字段吗?" 有 → LengthFieldBasedFrameDecoder;没有 → 必须先定协议。


6. 五个误区

误区 真相
"Netty 用多线程处理一个连接" 一个 Channel 绑一个 EventLoop
"零拷贝=完全不复制" 减少 CPU 拷贝
"ByteBuf 不用释放" 池化需 release()
"TCP 有消息边界" 字节流,需应用层协议
"业务逻辑可以直接放 EventLoop" 会阻塞整条连接

7. 自检(架构师版)

  1. Boss/Worker 分工?
  2. 为什么一个 Channel 只绑一个 EventLoop?
  3. 零拷贝的两层含义?
  4. ByteBuf 相比 ByteBuffer 的三个优势?
  5. 粘包的本质与解码器选择?

8. 下一篇

S17-X01 · 分布式八股速查

最后一篇是附录索引,随后进入 S20/S21 的 AI 工程系列。


本篇属于系列《S17 · 分布式与消息队列》。旧文来源:A-1846/1088/1089/1090/1092/1093/1094/1095/1096/1097/1091/2627/2319/504;扩展点 E-S17-016。

S17-A03 · Netty 与网络编程模型
https://www.clxhxhhr.top/posts/5432/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。