Netty底层探究

Netty线程模型

// Netty模型
1.Netty抽象出两组线程池BossGroupWorkerGroup,BossGroup专门负责接收客户端的连接,WorkerGroup专门负责网络的读写.
2.BossGroup和WorkerGroup类型都是NioEventLoopGroup.
(NioEventLoopGroup相当于一个事件循环线程组,这个组中含有多个事件循环线程,每一个事件循环线程是NioEventLoop)
3.每个NioEventLoop都有一个selector,用于监听注册在其上的socketChannel的网络通讯。
4.每个Boss NioEventLoop线程内部循环执行的步骤有 3 步
	a.处理accept事件,与client建立连接,生成 NioSocketChannel。 
	b.NioSocketChannel注册到某个worker  NIOEventLoop上的selector
	c.处理任务队列的任务,即runAllTask.
5.每个worker NIOEventLoop线程循环执行的步骤
   a.轮询注册到自己selector上的所有NioSocketChannel 的read, write事件
   b.处理 I/O 事件,即read/write 事件,在对应NioSocketChannel 处理业务
   c.runAllTasks处理任务队列TaskQueue的任务,一些耗时的业务处理一般可以放入TaskQueue中慢慢处理,这样不影响数据在pipeline中的流动处理.
6.每个worker NIOEventLoop处理NioSocketChannel业务时,会使用 pipeline (管道),管道中维护了很多 handler处理器用来处理channel中的数据.

Netty底层探究_第1张图片

Netty模块组件

// Bootstrap
Netty中用于启动客户端的引导类.
// ServerBootstrap
Netty中用于启动服务端的引导类.
// Future、ChannelFuture
Netty 中用于异步操作结果的接口,用于表示一个异步操作的结果或者状态.
// Channel
Netty网络通信的组件,能够用于执行网络I/O操作.
例如NioSocketChannel:异步的客户端TCP Socket连接.
// Selector
Netty基于Selector对象实现 I/O 多路复用,通过 Selector 一个线程可以监听多个连接的 Channel 事件.
// NioEventLoop
NioEventLoop 中维护了一个线程和任务队列。
// NioEventLoopGroup
NioEventLoopGroup,主要管理 eventLoop 的生命周期,可以理解为一个线程池.
// ChannelHandler
ChannelHandler是一个接口,处理 I/O 事件或拦截 I/O 操作,并将其转发到其 ChannelPipeline(业务处理链)中的下一个处理程序。
ChannelInboundHandler 用于处理入站 I/O 事件。
ChannelOutboundHandler 用于处理出站 I/O 操作。
// ChannelHandlerContext
保存 Channel 相关的所有上下文信息,同时关联一个 ChannelHandler 对象。
// ChannelPipline
保存ChannelHandlerList,用于处理或拦截 Channel 的入站事件和出站操作。
ChannelPipeline 实现了一种高级形式的拦截过滤器模式,使用户可以完全控制事件的处理方式,以及 Channel 中各个的 ChannelHandler 如何相互交互。如下图:

Netty底层探究_第2张图片

ByteBuf

ByteBuf 由一串字节数组构成。数组中每个字节用来存放信息.
ByteBuf 提供了两个索引,一个用于读取数据,一个用于写入数据.
如下图:
Netty底层探究_第3张图片

Netty编解码

网络中数据都是基于0101的二进制字节传输的。.发送方需要将数据编码转化为二进制字节,接收方收到二进制字节,再解码成数据.

Netty中的编解码是通过ChannelHandler来实现的。编码器用于将应用程序数据转换为字节,以便在网络上传输。解码器则用于将接收到的字节转换为应用程序数据。这些编解码器通常被添加到ChannelPipeline中,以便在数据传输过程中自动进行编解码操作。这种方式可以帮助简化网络通信过程中的数据处理和转换。

Netty粘包拆包

在网络通信中,由于数据传输的不确定性,可能会导致粘包和拆包的问题.
Netty底层探究_第4张图片

// 如上图客户端发送两个数据包:江山和美人
a.正常接收 -> 江山 美人
b.粘包 -> 江山美人
c.拆包 -> 江 山 美人 或者 江山 美 人

解决方案

1.消息定长度,传输的数据大小固定长度,例如每段的长度固定为100字节,如果不够空位补空格.
2.在数据包尾部添加特殊分隔符,比如下划线,中划线等,这种方法简单易行,但选择分隔符的时候一定要注意每条数据的内部一定不能出现分隔符。
3.发送长度:发送每条数据的时候,将数据的长度一并发送,比如可以选择每条数据的前4位是数据的长度,应用层处理时可以根据长度来判断每条数据的开始和结束。

你可能感兴趣的:(nio,后端)