Netty的原理

Netty的原理

Netty是什么呢?Netty是JBoss出品的高效的Java NIO开发框架。

Reactor模式

Netty使用了Reactor模式,包括三种模式:

  1. Reactor单线程模型
  2. Reactor多线程模型
  3. 主从多线程模型

实际上的Reactor模式,是基于Java NIO的,在他的基础上,抽象出来两个组件——Reactor和Handler两个组件:

  1. Reactor:负责响应IO事件,当检测到一个新的事件,将其发送给相应的Handler去处理;新的事件包含连接建立就绪、读就绪、写就绪等。
  2. Handler:将自身(handler)与事件绑定,负责事件的处理,完成channel的读入,完成处理业务逻辑后,负责将结果写出channel。
  3. Acceptor:接受客户端的请求,也可以看做一个Handler。

Reactor单线程模型

只有一个线程完成所有事情,包括接收客户端的TCP连接请求、监听事件、进行读取和写入套接字数据等。
在这里插入图片描述

对于一些小容量应用场景,可以使用单线程模型。但是对于高负载、大并发的应用却不合适,主要原因如下:

  1. 性能有极限,不能处理成百上千的事件 ,即便NIO线程的CPU负荷达到100%,也无法满足海量消息的编码、解码、读取和发送;
  2. 当NIO线程负载过重之后,性能将会下降,这会导致大量客户端连接超时,超时之后往往会进行重发,这更加重了NIO线程的负载,最终会导致大量消息积压和处理超时,NIO线程会成为系统的性能瓶颈;
  3. 可靠性问题:一旦NIO线程的某一个事件处理器(handle)发送故障或者阻塞时,会使其他所有的handle都不能进行,而且acceptor也会阻塞住,也就是说,整个系统通信模块都不可用,不能接收和处理外部消息,造成节点故障。

为了解决这些问题,演进出了Reactor多线程模型。

Reactor多线程模型:

Rector多线程模型与单线程模型最大的区别就是:有一个线程池处理真实的IO操作,也就是说,将诸多handle放入线程池中进行IO操作,而acceptor、reactor还是单线程,接受客户端的TCP连接请求。
在这里插入图片描述

Reactor多线程模型的特点:

  1. 有专门一个NIO线程-Acceptor线程用于监听服务端,接收客户端的TCP连接请求;
  2. 网络IO操作-读(handler)、写等由一个NIO线程池负责,它包含一个任务队列和N个可用的线程,由这些NIO线程负责消息的读取、解码、编码和发送;
  3. 1个NIO线程可以同时处理N条链路,但是1个链路只对应1个NIO线程,防止发生并发操作问题。

在绝大多数场景下,Reactor多线程模型都可以满足性能需求;但是,在极特殊应用场景中,一个NIO线程负责监听和处理所有的客户端连接可能会存在性能问题。

例如百万客户端并发连接,或者服务端需要对客户端的握手消息进行安全认证,认证本身非常损耗性能。在这类场景下,单独一个Acceptor线程可能会存在性能不足问题,为了解决性能问题,产生了第三种Reactor线程模型-主从Reactor多线程模型。

主从Reactor多线程模型

主从Reactor线程模型与Reactor多线程模型的最大区别就是:有一个主reactor监听连接,多个从reactor监听读写事件。也就是说,将一个Reactor分为主从两种,分别负责监听连接事件和读写事件。

这里MainReactor只有一个,但是subReactor可以有多个。

MainReactor会监控Acceptor线程池,而subReactor会监控Handler线程池。

Acceptor线程池只用于客户端的登录、握手和安全认证,一旦链路建立成功,就将链路注册到后端subReactor线程池的I/O线程上,有I/O线程负责后续的I/O操作。

在这里插入图片描述

即从多线程模型中由一个线程来监听连接事件和数据读写事件,拆分为一个线程监听连接事件,线程池的多个线程监听已经建立连接的套接字的数据读写事件,另外和多线程模型一样有专门的线程池处理真正的IO操作。

Netty的模式

说完Reacotr模型的三种形式,那么Netty是哪种呢?

其实,还有一种Reactor模型的变种,那就是去掉线程池的第三种形式的变种,这也 是Netty NIO的默认模式。
在实现上,Netty中的Boss类充当mainReactor,NioWorker类充当subReactor(默认 NioWorker的个数是Runtime.getRuntime().availableProcessors())。在处理新来的请求 时,NioWorker读完已收到的数据到ChannelBuffer中,之后触发ChannelPipeline中的ChannelHandler流。

  1. EventLoopGroup就相当于是Reactor,bossGroup对应主Reactor,workerGroup对应从Reactor
  2. TimeServerHandler就是Handler
  3. child开头的方法配置的是客户端channel,非child开头的方法配置的是服务端channel

NioEventLoop是Netty的Reactor线程,它在Netty Reactor线程模型中的职责如下:

  1. 作为服务端Acceptor线程,负责处理客户端的请求接入
  2. 作为客户端Connecor线程,负责注册监听连接操作位,用于判断异步连接结果
  3. 作为IO线程,监听网络读操作位,负责从SocketChannel中读取报文
  4. 作为IO线程,负责向SocketChannel写入报文发送给对方,如果发生写半包,会自动注册监听写事件,用于后续继续发送半包数据,直到数据全部发送完成
    如下图,是一个NioEventLoop的处理链:

在这里插入图片描述
注意:

  • handler处理链中的处理方法是串行化执行的

  • 一个客户端连接只注册到一个NioEventLoop上,避免了多个IO线程并发操作

  • Netty中模式具体是怎样的

原文链接:https://blog.csdn.net/qq_18603599/article/details/80768390

发布了67 篇原创文章 · 获赞 32 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_43751710/article/details/104807162
今日推荐