Netty 深入学习
在分布式系统、微服务架构中,网络通信是最基础也是最重要的一部分。
很多高性能框架(如 Dubbo、gRPC、RocketMQ、Elasticsearch 等)底层都依赖 Netty 来完成网络通信。
理解 Netty,首先要理解它背后的 NIO 网络模型设计思想。
传统网络编程的问题
在早期 Java 网络编程中,大多数程序使用的是 BIO(Blocking IO) 模型。
例如:
服务器每接入一个客户端连接,就创建一个线程。
一个连接 = 一个线程如果连接很多,比如:
1万连接 = 1万个线程这会带来几个严重问题:
线程资源消耗巨大
线程本身需要内存和调度成本。
线程上下文切换开销大
CPU需要频繁在不同线程之间切换。
系统扩展性差
连接数量一多,系统就容易崩溃。
因此,传统 BIO 并不适合 高并发网络服务。
NIO 的核心设计思想
为了解决 BIO 的问题,Java 提出了 NIO(Non-Blocking IO)。
NIO 的核心思想非常简单:
用少量线程,管理大量连接
它依赖三个核心组件:
Channel
Buffer
Selector这三者构成了 NIO 的核心架构。
Channel(通道)
Channel 可以理解为:
数据传输的管道
和传统 IO 不同的是:
传统 IO:
输入流 / 输出流而 Channel:
是双向的既可以读,也可以写。Channel 本质就是 网络连接的抽象。
Buffer(缓冲区)
在 NIO 中,所有数据都必须先进入 Buffer。
可以理解为:
数据的临时存储区域
数据流程:
网络 -> Buffer -> 程序
程序 -> Buffer -> 网络Selector(选择器)
Selector 是 NIO 最核心的组件。
它的作用是:
用一个线程管理多个 Channel
也就是:
一个线程
监听多个连接工作方式类似:
事件轮询流程:
Selector
|
监听多个 Channel
|
哪个 Channel 有事件
|
处理哪个Reactor 线程模型
Reactor 线程模型是一种 高并发网络服务器常用的设计模式。它的核心思想是:用少量线程,通过事件驱动的方式去处理大量网络连接。线程不再为每一个连接单独创建,而是通过监听网络事件(连接、读、写等),当某个连接有数据到达时再去处理它。这样就避免了大量线程带来的资源消耗和上下文切换问题,大大提升了服务器的并发处理能力。
Reactor 模型通常包含几个关键角色:
1、事件监听(Reactor)
负责监听网络事件,例如新的连接到来、数据可读、数据可写等。
2、连接接入(Acceptor)
当有新的客户端连接时,负责接收连接并注册到后续的处理线程中。
3、事件分发(Dispatcher)
将不同的网络事件分发给对应的处理逻辑。
4、业务处理(Handler)
真正执行业务逻辑,比如解析协议、处理请求、返回结果。
在 Netty 中,Reactor 模型通常体现为 BossGroup + WorkerGroup 的线程结构:
- Boss 线程:负责接收客户端连接
- Worker 线程:负责处理网络读写和业务逻辑
通过这种设计,Netty 可以用 少量线程处理成千上万的连接,这也是它能够实现高性能网络通信的核心原因。