Netty入门

前言:

传统的 IO 模型中,一个线程对应一个连接,当有一个新连接时会创建一个新的线程,死循环接收数据。大多情况时,只有少量时间是有数据可读的,因此会造成资源浪费。

在 NIO 模型中一个死循环检测多个连接是否有数据可读,这就是 selector,然后通过检查 selector 知道那些线程是有数据可读的,进而读取数据。

Java 中 NIO 使用比较繁琐,因而使用已经被封装的使用起来非常方便的框架—— Netty 。

传统IO 和 NIO 处理多个连接的图示:

使用阻塞 I/O 处理多个连接
【使用阻塞 I/O 处理多个连接】

使用 Selector 的非阻塞 I/O
【使用 Selector 的非阻塞 I/O】

1. Netty 是什么

Netty 是一个 异步事件驱动的网络应用框架,用于快速开发可维护的高性能服务器和客户端。

异步:异步非阻塞 I/O

事件驱动:当有事件触发时,才会调用处理器进行数据处理

网络应用框架:网络编程的支持

2. Netty 中的 Reactor 线程模型

前言中提到了传统阻塞的I/O 线程,Netty 中开多个线程,每个线程管理着一批连接。

Reactor 线程模型可分为单线程版 多线程版和主从模型版

2.1 单线程模型

单线程版: 一个Reactor线程负责连接,负责分发请求,顺序处理每个连接的业务逻辑。虽然一次可以处理多个请求,但实现上还是一个线程完成所有的任务。不适合多核CPU。

代码实现方式:

private EventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
                .group(group)
                .childHandler(new HeartbeatInitializer());

2.2 多线程模型

多线程版: 相比上一种模式,该模型在分配处理部分采用了多线程(线程池),可以解决 CPU 密集型的业务逻辑。但是在Acceptor连接线程上还是单个,如果服务是高I/O 的话还是不能满足需求,也没办法利用多核。

代码实现方式:

private EventLoopGroup boss = new NioEventLoopGroup(1);
private EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
                .group(boss,work)
                .childHandler(new HeartbeatInitializer());

2.3 主从模型版

主从模型:该模型相比第二种模型,是将Reactor分成两部分,mainReactor负责监听server socket,accept新连接;并将建立的socket分派给subReactor。subReactor负责多路分离已连接的socket,读写网络数据,对业务处理功能,其扔给worker线程池完成。通常,subReactor个数上可与CPU个数等同或为核数的两倍。

2.4 Netty 主从多线程模型

Netty 监听客户端连接是一个线程组管理的,而监听客户端读写的任务是由另一个线程组来管理的。Netty 的线程模型是 Reactor 模型的变种,那就是去掉线程池的第三种形式的变种,这也是 Netty NIO的默认模式。

netty线程模型

代码实现:

private EventLoopGroup boss = new NioEventLoopGroup();
private EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
                .group(boss,work)
                .childHandler(new HeartbeatInitializer());

在处理时也可加线程池进行处理,使其成为第三种模型。

3. Netty 基本概念

客户端和服务端连接图示:

3.1 NioEventLoop

服务端监听的端口,传统的 Server Socket。

开启两种线程,一种监听客户端连接,一种处理客户端读写。

3.2 Channel

客户端和服务端连接的封装,可以理解为Socket

在Channel连接的封装上面可以进行读写。

3.3 ChannelHandler

Pipeline 中的 ChannelHandler

对数据进行业务处理的逻辑。在逻辑处理链Pipeline上的逻辑处理。

3.4 Decoder 和 Encoder

编码和解码,基于TCP 通信的数据包是基于二进制的。客户端需要将一个Java对象按照通信协议编码为一个二进制数据包,服务端接受后需要进行拆包 将二进制数据包解码为Java对象,交给业务处理。处理后按照同样的通信协议进行编码给客户端返回。

3.5 ByteBuf

ByteBuf 是 Netty 对二进制数据抽象的数据结构,可以更方便的操作二进制数据。

3.6 Pipeline

Channel 上面逻辑处理链

posted @ 2020-03-22 21:37  胖大星-  阅读(186)  评论(0编辑  收藏  举报