12.Netty源码之整体架构脉络
Netty 整体架构脉络
Netty 的逻辑处理架构为典型网络分层架构设计,共分为网络通信层、事件调度层、服务编排层,每一层各司其职。

网络通信层
网络通信层的职责是执行网络 I/O 的操作。它支持多种网络协议和 I/O 模型的连接操作。当网络数据读取到内核缓冲区后,会触发各种网络事件,这些网络事件会分发给事件调度层进行处理。
网络通信层的核心组件包含BootStrap、ServerBootStrap、Channel三个组件。
BootStrap
Bootstrap 是“引导”的意思,它主要负责整个 Netty 程序的启动、初始化、服务器连接等过程,它相当于一条主线,串联了 Netty 的其他核心组件。
Netty 中的引导器共分为两种类型:
一个为用于客户端引导的 Bootstrap。
另一个为用于服务端引导的 ServerBootStrap,它们都继承自抽象类 AbstractBootstrap。
Bootstrap 和 ServerBootStrap 十分相似,两者非常重要的区别在于:
客户端 Bootstrap 可用于连接远端服务器,只绑定一个 EventLoopGroup。
而 ServerBootStrap 则用于服务端启动绑定本地端口,会绑定两个 EventLoopGroup,这两个 EventLoopGroup 通常称为 Boss 和 Worker。
为什么客户端的BootStrap要绑定一个EventLoopGroup呢?
因为服务器端发送消息给客户端,客户端也是需要一个EventLoopGroup处理。
ServerBootStrap 中的 Boss 和 Worker 是什么角色呢?它们之间又是什么关系?
这里的 Boss 和 Worker 可以理解为“老板”和“员工”的关系。
每个服务器中都会有一个 Boss,也会有一群做事情的 Worker。
Boss 会不停地接收新的连接,然后将连接分配给一个个 Worker 处理连接。
Channel
比如ServerSocketChannel NioSocketChannel。
Channel 的字面意思是“通道”,它是网络通信的载体。
Channel提供了基本的 API 用于网络 I/O 操作,
如 register:注册到eventloop、bind:绑定端口、connect:连接服务器端、read、write、flush 等。
Netty 自己实现的 Channel 是以 JDK的NIOChannel 为基础的,相比较于 JDK NIO,Netty 的 Channel 提供了更高层次的抽象,同时屏蔽了底层 Socket 的复杂性,赋予了 Channel 更加强大的功能,你在使用 Netty 时基本不需要再与 Java Socket 类直接打交道。
下图是 Channel 家族的图谱。AbstractChannel 是整个家族的基类,派生出 AbstractNioChannel、
AbstractOioChannel、AbstractEpollChannel 等子类,每一种都代表了不同的 I/O 模型和协议类型。
常用的 Channel 实现类有:

NioServerSocketChannel 异步TCP服务端。可以监听接入TCP连接的通道。 NioSocketChannel 异步TCP客户端。客户端跟服务端进行通信的。是连接到TCP网络socket(套接字)的通道 OioServerSocketChannel 同步 TCP 服务端。 OioSocketChannel 同步 TCP 客户端。 NioDatagramChannel 异步 UDP 连接。 OioDatagramChannel 同步 UDP 连接。
当然 Channel 会有多种状态,如连接建立、连接注册、数据读写、连接销毁等。随着状态的变化,Channel 处于不同的生命周期,每一种状态都会绑定相应的事件回调,下面的表格我列举了 Channel 最常见的状态所对应的事件回调。
事件 说明 channelRegistered Channel 创建后被注册到EventLoop上 channelUnregistered Channel 创建后从EventLoop取消注册 channelActive Channel 处于就绪状态,可以被读写 channelInactive Channel 处于非就绪状态 channelRead Channel 可以从远端读取到数据 channelReadComplete Channel 读取数据完成
BootStrap 和 ServerBootStrap 分别负责客户端和服务端的启动,它们是非常强大的辅助工具类;
Channel 是网络通信的载体,提供了与底层 Socket 交互的能力。
那么 Channel 生命周期内的事件都是如何被处理的呢?
那就是 Netty 事件调度层的工作职责了。
事件调度层
事件调度层的职责是通过 Reactor 线程模型对各类事件进行聚合处理,通过 Selector 主循环线程集成多种事件( I/O
事件、信号事件、定时事件等),实际的业务处理逻辑是交由服务编排层中相关的 Handler 完成。
事件调度层的核心组件包括 EventLoopGroup、EventLoop。
EventLoopGroup
EventLoopGroup 本质是一个线程池,主要负责接收 I/O 请求,并分配线程执行处理请求。
在下图中,我为你讲述了 EventLoopGroups、EventLoop 与 Channel 的关系。

EventLoopGroup、EventLoop、Channel的关系
从上图中,我们可以总结出 EventLoopGroup、EventLoop、Channel 的几点关系。
EventLoop和线程绑定
一个 EventLoopGroup 往往包含一个或者多个 EventLoop。EventLoop 同一时间会与一个线程绑定,每个EventLoop负责处理多个 Channel
1个EventLoop可以理解为1个线程 ,EventLoop 用于处理 Channel 生命周期内的所有 I/O 事件。
如 accept、connect、read、write 等 I/O 事件。
1个EventLoop处理N个Channel
1个channel绑定1个EventLoop
每新建一个 Channel,EventLoopGroup 会选择一个 EventLoop 与其绑定。
该 Channel 在生命周期内都可以对 EventLoop 进行多次绑定和解绑。
下图是 EventLoopGroup 的家族图谱。可以看出 Netty 提供了 EventLoopGroup 的多种实现,而且 EventLoop 则是 EventLoopGroup 的子接口,所以也可以把 EventLoop 理解为 EventLoopGroup,但是它只包含一个 EventLoop 。

EventLoop的实现类是 NioEventLoop。
EventLoopGroup 的实现类是 NioEventLoopGroup。
NioEventLoopGroup 也是 Netty 中最被推荐使用的线程模型。
NioEventLoopGroup 继承于 MultiThreadEventLoopGroup,是基于 NIO 模型开发的,可以把 NioEventLoopGroup 理解为一个线程池,NioEventLoop理解为1个线程。
每个线程负责处理多个 Channel,而同一个 Channel 只会对应一个线程。
EventLoopGroup 是 Netty 的核心处理引擎,那么 EventLoopGroup和之前所提到的 Reactor 线程模型到底是什么关系呢?
其实 EventLoopGroup 是 Netty Reactor 线程模型的具体实现方式,Netty 通过创建不同的 EventLoopGroup 参数配置,就可以支持 Reactor 的三种线程模型:
单线程模型:EventLoopGroup 只包含一个 EventLoop,Boss 和 Worker 使用同一个EventLoopGroup;
多线程模型:EventLoopGroup 包含多个 EventLoop,Boss 和 Worker 使用同一个EventLoopGroup;
主从多线程模型:EventLoopGroup 包含多个 EventLoop,Boss 是主 Reactor,Worker 是从 Reactor,它们分别使用不同的 EventLoopGroup,主 Reactor 负责接受新的网络连接 Channel 创建,然后把 Channel 注册到从 Reactor。从 Reactor负责监听读写事件。
服务编排层
服务编排层的职责是负责组装各类服务,它是 Netty 的核心处理链,用以实现网络事件的动态编排和有序传播。
服务编排层的核心组件包括 ChannelPipeline、ChannelHandler、ChannelHandlerContext。
handler方法和childHandler方法
java 在基类AbstractBootstrap有handler方法,目的是添加一个handler,监听Bootstrap的动作,客户端的Bootstrap中,继承了这一点。 在服务端的ServerBootstrap中增加了一个方法childHandler,它的目的是添加handler,用来监听已经连接的客户端的Channel的动作和状态。 handler()和childHandler()的主要区别是,handler()是发生在初始化的时候。初始化指的是accept接收到请求,对客户端socketChannel进行初始化。 childHandler()是发生在客户端连接之后。 也就是说,如果需要在客户端连接前的请求进行handler处理,则需要配置在handler()方法中处理,如果是处理客户端连接之后的handler,则需要配置在childHandler()。 通过handler添加的handlers是对bossGroup线程组起作用,通过childHandler添加的handlers是对workerGroup线程组起作用,客户端Bootstrap只有handler()方法,因为客户端只需要一个事件线程组( b.childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast(serverHandler); } }); pipeline是伴随Channel的存在而存在的,交互信息通过它进行传递,我们可以addLast(或者addFirst)多个handler,第一个参数是名字,无具体要求,如果填写null,系统会自动命名。
ChannelPipeline
ChannelPipeline 是 Netty 的核心编排组件,负责组装各种 ChannelHandler,实际数据的编解码以及加工处理操作都是由 ChannelHandler 完成的。
ChannelPipeline 可以理解为ChannelHandler 的实例列表——内部通过双向链表将不同的 ChannelHandler 链接在一起。当 I/O 读写事件触发时,ChannelPipeline 会依次调用 ChannelHandler 列表对 Channel 的数据进行拦截和处理。
ChannelPipeline 是线程安全的,因为每一个新的 Channel 都会对应绑定一个新的 ChannelPipeline。
一个 ChannelPipeline 关联一个 EventLoop,一个 EventLoop 仅会绑定一个线程。
ChannelPipeline、ChannelHandler 都是高度可定制的组件。
开发者可以通过这两个核心组件掌握对 Channel 数据操作的控制权。下面我们看一下 ChannelPipeline 的结构图:

从上图可以看出,ChannelPipeline 中包含入站 ChannelInboundHandler 和出站 ChannelOutboundHandler 两种处理器,我们结合客户端和服务端的数据收发流程来理解 Netty 的这两个概念。

客户端和服务端都有各自的 ChannelPipeline。
以客户端为例,数据从客户端发向服务端,该过程称为出站,反之则称为入站。
数据入站会由一系列 服务器端的InBoundHandler 处理,然后再以相反方向的 服务器端的OutBoundHandler 处理后完成出站。
我们经常使用的编码 Encoder 是出站操作,解码 Decoder 是入站操作。
服务端接收到客户端数据后,需要先经过 Decoder 入站处理后,再通过 Encoder 出站通知客户端。
所以客户端和服务端一次完整的请求应答过程可以分为4个步骤:
客户端出站(编码请求数据)、
服务端入站(解码数据并执行业务逻辑)、
服务端出站(编码响应结果)
客户端入站(解码响应数据,执行业务逻辑)。
ChannelHandler&ChannelHandlerContext
数据的编解码工作以及其他转换工作实际都是通过 ChannelHandler 处理的。
站在开发者的角度,最需要关注的就是 ChannelHandler,我们很少会直接操作 Channel,都是通过 ChannelHandler 间接完成。
下图描述了 Channel 与 ChannelPipeline 的关系,从图中可以看出,每创建一个 Channel 都会绑定一个新的 ChannelPipeline,ChannelPipeline 中每加入一个 ChannelHandler ,ChannelHandler都会绑定一个 ChannelHandlerContext。
ChannelPipeline、ChannelHandlerContext、ChannelHandler 三个组件的关系是密切相关的,那么你一定会有疑问,每个 ChannelHandler 绑定ChannelHandlerContext 的作用是什么呢?

ChannelHandlerContext 用于保存 ChannelHandler 上下文,通过 ChannelHandlerContext 我们可以知道 ChannelPipeline 和 ChannelHandler 的关联关系。
ChannelHandlerContext 可以实现 ChannelHandler 之间的交互,ChannelHandlerContext 包含了
ChannelHandler 生命周期的所有事件,如 connect、bind、read、flush、write、close 等。
ChannelHandler 中又持有ChannelPipeline 。
此外,你可以试想这样一个场景。
如果每个 ChannelHandler 都有一些通用的逻辑需要实现,没有 ChannelHandlerContext 这层模型抽象,你是不是需要写很多相同的代码呢?
每个新建的 Channel 会绑定一个新的ChannelPipeline,每一个 ChannelPipeline 都包含多个 ChannelHandlerContext,所有 ChannelHandlerContext 之间组成了双向链表。
又因为每个 ChannelHandler 都对应一个 ChannelHandlerContext,所以实际上 ChannelPipeline 维护的是它与 ChannelHandlerContext 的关系。
以上便是 Netty 的逻辑处理架构,可以看出 Netty 的架构分层设计得非常合理,屏蔽了底层 NIO 以及框架层的实现细节,对于业务开发者来说,只需要关注业务逻辑的编排和实现即可。
组件关系梳理
当你了解每个 Netty 核心组件的概念后。你会好奇这些组件之间如何协作?结合客户端和服务端的交互流程,我画了一张图,为你完整地梳理一遍 Netty 内部逻辑的流转。

Netty整体流程
java 服务端 启动初始化时有 Boss EventLoopGroup 和 Worker EventLoopGroup 两个组件,其中 Boss-EventLoopGroup负责监听网络连接事件。当有新的网络连接事件到达时,则创建Channel并将 Channel 注册到 Worker-EventLoopGroup。 Worker-EventLoopGroup 会被分配一个 EventLoop 负责处理该 Channel 的读写事件。每个 EventLoop 都是单线程的,通过 Selector 进行事件循环。每一个 nioeventloop 的 selector 对应的是同一个对象,这两个对象是一一对应的。 当客户端发起 I/O 读写事件时,会通过selector绑定EventLoop , 服务端 EventLoop 会进行数据的读取,然后通过 Pipeline 触发各种监听器进行数据的加工处理。 客户端数据会被传递到 ChannelPipeline 的第一个 ChannelInboundHandler 中,数据处理完成后,将加工完成的数据传递给下一个 ChannelInboundHandler。 当数据写回客户端时,会将处理结果在 ChannelPipeline 的 ChannelOutboundHandler 中传播,最后到达客户端。
以上便是 Netty 各个组件的整体交互流程,你只需要对每个组件的工作职责有所了解,心中可以串成一条流水线即可,具体每个组件的实现原理后续我们会深入介绍。
视频学习链接:https://www.bilibili.com/video/BV19g4y1H7iy?p=3&vd_source=2fe0aba0a7e0c99e9d0d910556f2b12f
相关文章:
12.Netty源码之整体架构脉络
Netty 整体架构脉络 Netty 的逻辑处理架构为典型网络分层架构设计,共分为网络通信层、事件调度层、服务编排层,每一层各司其职。 网络通信层 网络通信层的职责是执行网络 I/O 的操作。它支持多种网络协议和 I/O 模型的连接操作。当网络数据读取到内核缓冲…...
【ArcGIS Pro二次开发】(54):三调名称转用地用海名称
三调地类和用地用海地类之间有点相似但并不一致。 在做规划时,拿到的三调,都需要将三调地类转换为用地用海地类,然后才能做后续的工作。 一般情况下,三调转用地用海存在【一对一,多对一和一对多】3种情况。 前2种情况…...
3D Tiles官方示例资源下载链接
本文列出Cesium官方提供的 3D Tiles 1.0和1.1规范的9个示例切块集(tileset)。 有关如何使用本地服务器托管这些示例的详细信息,请参阅 INSTRUCTIONS.md。 推荐:用 NSDT设计器 快速搭建可编程3D场景。 1、Metadata Granularities …...
【Java】分支结构习题
【Java】分支结构 文章目录 【Java】分支结构题1 :数字9 出现的次数题2 :计算1/1-1/21/3-1/41/5 …… 1/99 - 1/100 的值。题3 :猜数字题4 :牛客BC110 X图案题5 :输出一个整数的每一位题6 : 模拟三次密码输…...
删除主表 子表外键没有索引的性能优化
整个表147M,执行时一个CPU耗尽, buffer gets 超过1个G, 启用并行也没有用 今天开发的同事问有个表上的数据为什么删不掉?我看了一下,也就不到100000条数据,表上有外键,等了5分钟hang在那里&…...
面向切面编程AOP
面向切面编程简介 IoC使软件组件松耦合。AOP让你能够捕捉系统中经常使用的功能,把它转化成组件。 AOP(Aspect Oriented Programming):面向切面编程,面向方面编程。(AOP是一种编程技术) AOP是对…...
大学生活题解
样例输入: 3 .xA ... Bx.样例输出: 6思路分析: 这道题只需要在正常的广搜模板上多维护一个— —方向,如果当前改变方向,就坐标不变,方向变,步数加一;否则坐标变,方向不…...
flask的配置项
flask的配置项 为了使 Flask 应用程序正常运行,有多种配置选项需要考虑。下面是一些基本的 Flask 配置选项: DEBUG: 这个配置项决定 Flask 是否应该在调试模式下运行。如果这个值被设为 True,Flask 将会提供更详细的错误信息,并…...
暑假刷题第16天--7/28
143. 最大异或对 - AcWing题库(字典树) #include<iostream> using namespace std; const int N100005; int a[N]; int nex[10000007][2],cnt; void insert(int x){int p0;for(int i30;i>0;i--){int ux>>i&1;if(!nex[p][u])nex[p][u]…...
vue vite ts electron ipc arm64
初始化 npm init vue # 全选 yes npm i # 进入项目目录后使用 npm install electron electron-builder -D npm install commander -D # 额外组件增加文件 新建 plugins 文件夹 src/background.ts 属于主进程 ipcMain.on、ipcMain.handle 都用于主进程监听 ipc,…...
数据分析-关于指标和指标体系
一、电商指标体系 二、指标体系的作用 三、统计学中基本的分析手段...
Vue+ElementUI操作确认框及提示框的使用
在进行数据增删改查操作中为保证用户的使用体验,通常需要显示相关操作的确认信息以及操作结果的通知信息。文章以数据的下载和删除提示为例进行了简要实现,点击下载以及删除按钮,会出现对相关信息的提示,操作结果如下所示。 点击…...
宋浩线性代数笔记(二)矩阵及其性质
更新线性代数第二章——矩阵,本章为线代学科最核心的一章,知识点多而杂碎,务必仔细学习。 重难点在于: 1.矩阵的乘法运算 2.逆矩阵、伴随矩阵的求解 3.矩阵的初等变换 4.矩阵的秩 (去年写的字,属实有点ugl…...
Linux之Shell 编程详解(二)
第 9 章 正则表达式入门 正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文 本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。在 Linux 中,grep, sed,awk 等文本处理工具都支持…...
TCP网络通信编程之字节流
目录 【TCP字节流编程】 // 网络编程中,一定是server端先运行 【案例1】 【思路分析】 【客户端代码】 【服务端代码】 【结果展示】 【案例2】 【题目描述】 【注意事项】 【服务端代码】 【客户端代码】 【代码结果】 【TCP字节流编程】 // 网络编程中&a…...
【暑期每日一练】 day8
目录 选择题 (1) 解析: (2) 解析: (3) 解析: (4) 解析: (5) 解析: 编程题 题一 描述…...
maven的基本学习
maven https://www.bilibili.com/video/BV14j411S76G?p1&vd_source5c648979fd92a0f7ba8de0cde4f02a6e 1.简介 1.1介绍 Maven翻译为"专家"、“内行”,是Apache下的一个纯Java开发的开源项目。基于项目对象模型(缩写:POM)概念,Maven利用一…...
疲劳驾驶检测和识别2:Pytorch实现疲劳驾驶检测和识别(含疲劳驾驶数据集和训练代码)
疲劳驾驶检测和识别2:Pytorch实现疲劳驾驶检测和识别(含疲劳驾驶数据集和训练代码) 目录 疲劳驾驶检测和识别2:Pytorch实现疲劳驾驶检测和识别(含疲劳驾驶数据集和训练代码) 1.疲劳驾驶检测和识别方法 2.疲劳驾驶数据集 (1)疲…...
安防监控视频汇聚EasyCVR修改录像计划等待时间较长,是什么原因?
安防监控视频EasyCVR视频融合汇聚平台基于云边端智能协同,支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发等。音视频流媒体视频平台EasyCVR拓展性强,视频能力丰富,具体可实现视频监控直播、视频轮播、视频录像、云存储、回放与检…...
EXCEL数据自动web网页查询----高效工作,做个监工
目的 自动将excel将数据填充到web网页,将反馈的数据粘贴到excel表 准备 24KB的鼠标连点器软件(文末附链接)、Excel 宏模块 优势 不需要编程、web验证、爬虫等风险提示。轻量、稳定、安全。 缺点 效率没那么快 演示 宏环境 ht…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
