学习资料
https://www.bilibili.com/video/BV1cb411F7En
https://www.bilibili.com/video/BV1DJ411m7NR
1. netty 要解决的问题

2. netty 是什么
-
异步事件驱动框架,用于快速开发高性能服务和客户端
-
封装了JDK底层BIO和NIO模型,提供高度可用的API
-
自带编码解码器解决拆包粘包问题,用户只关心业务逻辑
-
精心设计的Reactor线程模型支持高并发海量连接
-
自带协议栈

3. netty高性能架构设计
3.1 netty架构
netty的IO是同步的,处理是异步的

第一层:Reactor通信调度层
-
由一些列辅助类完成,包括Reactor线程 NioEventLoop 以及其父类、NioSocketChannel/NioServerSocketChannel以及其父类、
ByteBuffer以及其衍生出来的各种 Buffer、Unsafe以及其衍生出来的各种内部类等 -
该层的主要职责就是监听网络的读写和连接操作,负责将网络层的数据读取到内存缓存中,然后触发各种网络事件
-
例如连接池、连接激活、读事件、写事件。将这些事件触发到pipeLine中,由PipeLine充当的职责链进行后续的处理。
第二层:职责链PipeLine
-
负责事件在职责链中的有序传播,同时负责动态的编排责任链,职责链可以选择监听和处理自己关心的事情,它可以拦截处理和向前/向后传播事件。
-
不同应用的Handler节点的功能也不同。通常情况下,往往会触发编解码Handler用于消息的编解码,它可以将外部的协议消息转换成内部的POJO对象
-
这样上层业务侧只需要关心处理业务逻辑即可。不需要感知底层的协议差异和线程模型差异,实现了架构层面的分层隔离
第三层:业务逻辑编排层
-
一类是纯粹的业务逻辑编排
-
一类是其他的应用层协议插件,用于特性协议相关的会话和链路管理。例如CMPP协议,用于管理和中国移动短信的对接。
3.2 netty线程模型
传统IO



Reactor模式

- Reactor模式,通过一个或者多个输入同时传递给服务处理器的模式(基于事件驱动)
- 服务器端程序处理传入的多个请求,并将它们同步分派到响应的处理线程,因此Reactor模式也叫做Dispatcher模式
-
Reactor模式使用IO复用监听事件,收到事件后,分发给某个线程(进程)。这点就是网络服务器并发处理关键
3.2.1 单Reactor单线程



最开始 NIO 是基于单线程实现的,所有的 I/O 操作都是在一个 NIO 线程上完成。由于 NIO 是非阻塞 I/O,理论上一个线程可以完成所有的 I/O 操作。但 NIO 其实还不算真正地实现了非阻塞 I/O 操作,因为读写 I/O 操作时用户进程还是处于阻塞状态,这种方式在高负载、高并发的场景下会存在性能瓶颈,一个 NIO 线程如果同时处理上万连接的 I/O 操作,系统是无法支撑这种量级的请求的。

3.2.2 单Reactor多线程

- Reactor对象通过select监控客户端请求事件,收到事件后,通过Dispatch进行分发
- 如果建立完成连接请求,则由Acceptor通过accept处理连接请求,然后创一个Handler对象处理完成连接后的各种事件
- 如果不是连接请求,则由reactor分发调用连接对应的handler来处理
- handler只负责响应事件,不做具体的业务处理,通过read读取数据后,会分发给后面的worker线程池的某个线程处理业务
-
worker线程池会分配独立线程完成真正的业务,并将结果返回给handler。
为了解决这种单线程的 NIO 在高负载、高并发场景下的性能瓶颈,后来使用了线程池。在 Tomcat 和 Netty 中都使用了一个 Acceptor 线程来监听连接请求事件,当连接成功之后,会将建立的连接注册到多路复用器中,一旦监听到事件,将交给 Worker 线程池来负责处理。大多数情况下,这种线程模型可以满足性能要求,但如果连接的客户端再上一个量级,一个 Acceptor 线程可能会存在性能瓶颈。
3.2.3 主从Reactor多线程
- Reactor主线程MainReactor对象通过select监听连接时间,收到事件后,通过Acceptor处理连接事件
- 当Acceptor处理连接事件后,MainReactor将连接分配给SubReactor
- subReactor将连接加入到连接队列进行监听,并创建handler进行各种事件处理
- 当有新事件发生时,subreactor就会调用对应handler处理
- handler通过read读取数据,分发给后面的worker线程处理
- worker线程池分配独立的worker线程进行业务处理,并返回结果
- handler收到响应的结果后,通过send将结果返回给client
- Reactor主线程可以对应多个Reactor子线程,即MainReactor。可以关联多个subreactor



现在主流通信框架中的 NIO 通信框架都是基于主从 Reactor 线程模型来实现的。在这个模型中,Acceptor 不再是一个单独的 NIO 线程,而是一个线程池。Acceptor 接收到客户端的 TCP 连接请求,建立连接之后,后续的 I/O 操作将交给 Worker I/O 线程。
4 Netty 模型
4.1
- BossGroup线程维护selector,只关注Accept
- 当接收到Accept事件,获取到对应的SocketChannel,封装成NIOSocketChannel并注册到Worker线程(事件循环),并进行维护
-
当worker线程监听到selecotr中通道发生自己感兴趣的事件后,就进行处理。注意handler已经加入到通道
4.2
- netty抽象出两组线程池。bossGroup专门负责接收客户端的连接,workGroup专门负责网络的读写
- BossGroup和WorkGroup类型都是NioEventLoopGroup
- NioEventLoopGroup相当于一个事件循环组,这个组中含有多个事件循环,每一个事件都是NioEventLoop
- NioEventLoop表示一个不断循环的执行处理任务的线程。每个NioEventLoop都有一个Selector,用于监听绑定在其上的Socket的网路通讯。
- NioEventLoopGroup可以有多个线程,即可以含有多个NioEventLoop
- 每个Boss NioEventLoop执行的步骤有三步
- 轮询accept事件
- 处理accept事件,与client建立连接,生成NioSocketChannel,并将其注册到某个worker NioEventLoop上的 selector。
- 处理任务队列的任务,即 runAllTasks
- 每个 worker NioEventLoop循环执行的步骤
- 轮询read、write事件
- 处理IO事件,即read、write事件,在对应NioSocketChannel处理
- 处理任务队列的任务
-
每个Worker NIOEventLoop处理业务时,会使用pipeline(管道)。pipeline中包含了channel,即通过pipeline可以获得对应通道,管道中维护了很多的处理器
网友评论