导航菜单
首页 » 梦之城下载 » 正文

肿瘤-高性能:《一遍文章带你看懂 Netty国际》

【概述】

Netty是由JBOSS供给的依据Java NIO的开源结构,Netty供给异步非堵塞、事情驱动、高功用、高牢靠、高可定制性的网络运用程序和东西,可用于开发服务端和客户端。

一. Netty是什么

Netty是一个高功用、异步事情驱动的NIO结构,依据JAVA NIO供给的API完结。它供给了对TCP、UDP和文件传输的支撑

作为一个异步NIO结构,Netty的一切IO操作都是异步非堵塞的,经过Future-Listener机制,用户能够便利的自动获取或许经过告诉机制取得IO操作成果。

作为当时最盛行的NIO结构,Netty在互联网范畴、大数据分布式核算范畴、游戏职业、通讯职业等取得了广泛的运用,一些业界闻名的开源组件也依据Netty的NIO结构构建。

二、 Netty线程模型

在JAVA NIO方面Selector给Reactor办法供给了根底,Netty结合Selector和Reactor办法规划了高效的线程模型。先来看下Reactor办法:

(一)、Reactor办法

Wikipedia这么解说Reactor模型:

“The reactor design pattern is an event handling pattern for handling service requests delivered concurrently by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to associated requ吹牛est handlers.”。

首要Reactor办法首要是事情驱动的,有一个或许多个并发输入源,有一个Server Handler和多个Request Handlers

这个Service Handler会同步的将输入的恳求多路复用的分发给相应的Request Handler。

能够如下图所示:

从结构上有点相似生产者和顾客模型,即一个或多个生产者将事情放入一个Queue中,而一个或许多个顾客自动的从这个行列中poll事情来处理;

而Reactor办法则没有Queue来做缓冲,每逢一个事情输入到Service Handler之后,该Service Hand肿瘤-高性能:《一遍文章带你看懂 Netty国际》ler会自动依据不同的Evnent类型将其分发给对应的Request Handler来处理。

(二)、 Reator办法的完结

关于Java NIO 结构Reator办法,Doug lea在《Scalable IO in Java》中给了很好的论述,这儿截取PPT对Reator办法的完结进行阐明

1、第一种完结模型如下:

这是最简略的Reactor单线程模型,因为Reactor办法运用的是异步非堵塞IO,一切的IO操作都不会被堵塞,理论上一个线程能够独立处理一切的IO操作。

这时Reactor线程是个多面手,担任多路别离套接字,Accept新衔接,并分发恳求到处理链中。

关于一些小容量运用场景,能够运用到单线程模型。但关于高负载,大并发的运用却不适宜,主要原因如下:

1)、当一个NIO线程一起处理成百上千的链路,功用上无法支撑,即便NIO线程的CPU负荷到达100%,也无法彻底处理音讯

2)、当NIO线程负载过重后,处理速度会肿瘤-高性能:《一遍文章带你看懂 Netty国际》变慢,会导致很多客户端衔接超时,超时之后往往会重发,更加剧了NIO线程的负载。肿瘤-高性能:《一遍文章带你看懂 Netty国际》

3)、牢靠性低,一个线程意外死循环,会导致整个通讯体系不行用

为了处理这些问题,呈现了Reactor多线程模型。

2、Reactor多线程模型:

比较上一种办法,该模型在处理链部分选用了多线程(线程池)。

在绝大多数场景下,该模型都能满意功用需求。可是,在一些特别的运用场景下,如服务器会对客户端的握手音讯进行安全认证。这类场景下,独自的一个Acceptor线程或许会存在功用缺乏的问题。

为了处理这些问题,产生了第三种Reactor线程模型

3、Reactor主从模型

该模型比较第二种模型,是将Reactor分红两部分,mainReactor担任监听server socket,accept新衔接;并将树立的socket分派给subReactor。

subReactor担任多路别离已衔接的socket,读写网络数据,对事务处理功用,其扔给worker线程池完结。一般,subReactor个数上可与CPU个数同等。

(三)、Netty模型

其实Netty的线程模型是Reactor模型的变种,那便是去掉线程池的第三种办法的变种,这也是Netty NIO的默许办法。

Netty中Reactor办法的参与者主要有下面一些组件:

1、Selector

2、EventLoopGroup/EventLoop

3、ChannelPipeline

Selector即为NIO中供给的SelectableChannel多路复用器,充任着demultiplexer的人物,这儿不再赘述;下面对别的两种功用和其在Netty之Reactor办法中扮演的人物进行介绍。

三、EventLoopGroup / EventLoop

当体系在运转进程中,假如频频的进行线程上下文切换,会带来额定的功用损耗。

多线程并发履行某个事务流程,事务开发者还需求时间对线程安全保持警惕,哪些数据或许会被并发修正,怎么维护?这不只降低了开发功率,也会带来额定的功用损耗。

为了处理上述问题,Netty选用了串行化规划理念

从音讯的读取、编码以及后续Handler的履行,一直都由IO线程EventLoop担任,这就意味着整个流程不会进行线程上下文的切换,数据也不会面对被并发修正的危险。这也解说了为什么Netty线程模型去掉了Reactor主从模型中线程池。

EventLoopGroup是一组EventLoop的笼统,EventLoopGroup供给next接口,能够从一组EventLoop里边依照必定规矩获取其间一个EventLoop来处理使命

关于EventLoopGroup这儿需求了解的是在Netty中,在Netty服务器编程中咱们需求BossEventLoopGroup和WorkerEventLoopGroup两个EventLoopGroup来进行作业。

一般一个服务端口即一个ServerSocketChannel对应一个Selector和一个EventLoop线程,也便是说BossEventLoopGroup的线程数参数为1。

BossEventLoop担任接纳客户端的衔接并将SocketChannel交给WorkerEventLoopGroup来进行IO处理。

EventLoop的完结充任Reactor办法中的分发(Dispatcher)的人物。

四、ChannelPipeline

ChannelPipeline其实是担任着Reactor办法中的恳求处理器这个人物。

ChannelPipeline的默许完结是DefaultChannelPipeline,DefaultChannelPipeline自身维护着一个用户不行见的tail和head的ChannelHandler,他们别离坐落链表行列的头部和尾部。tail在更上层的部分,而head在接近网络层的方向。

在Netty中关于ChannelHandler有两个重要的接口,ChannelInBoundHandler和ChannelOutBoundHandler。

inbound能够理解为网络数据从外部流向体系内部,而outbound能够理解为网络数据从体系内部流向体系外部。

用户完结的ChannelHandler能够依据需求完结其间一个或多个接口,将其放入Pipeline中的链表行列中,ChannelPipeline会依据不同的IO事情类型来找到相应的Handler来处理

一起链表行列是职责链办法的一种变种,自上而下或自下而上一切满意事情相关的Handler都会对事情进行处理。

ChannelInBoundHandler对从客户端发往服务器的报文进行处理,一般用来履行半包/粘包,解码,读取数据,事务处理等;

ChannelOutBoundHandler对从服务器发往客户端的报文进行处理,一般用来进行编码,发送报文到客户端。

下图是对ChannelPipeline履行进程的阐明:

五、Buffer

Netty供给的经过扩展的Buffer相对NIO中的有个许多优势,作为数据存取十分重要的一块,咱们来看看Netty中的Buffer有什么特色。

(一)、ByteBuf读写指针

1、在ByteBuffer中,读写指针都是position,而在ByteBuf中,读写指针别离为readerIndex和writerIndex

2、直观看上去ByteBuffer仅用了一个指针就完结了两个指针的功用,节省了变量,可是当关于ByteBuffer的读写状况切换的时分必需要调用flip办法,而当下一次写之前,必需要将Buffe中的内容读完,再调用clear办法。

3、每次读之前调用flip,写之前调用clear,这样无疑给开发带来了繁琐的过程,并且内容没有读完是不能写的,这样十分不灵敏。

4、比较之下咱们看看ByteBuf,读的时分只是依靠readerIndex指针,写的时分只是依靠writerIndex指针,不需每次读写之前调用对应的办法,并且没有有必要一次读完的约束。

(二)、零复制

1、Netty的接纳和发送ByteBuffer选用DIRECT BUFFERS,运用堆外直接内存进行Socket读写,不需求进行字节缓冲区的二次复制。

2、假如运用传统的堆内存(HEAP BUFFERS)进行Socket读写,JVM会将堆内存Buffer复制一份到直接内存中,然后才写入Socket中。比较于堆外直接内存,音讯在发送进程中多了一次缓冲区的内存复制。

3、Netty供给了组合Buffer方针,能够聚合多个ByteBuffer方针,用户能够像操作一个Buffer那样便利的对组合Buffer进行操作,避免了传统经过内存复制的办法将几个小Buffer合并成一个大的Buffer。

4、Netty的文件传输选用了transferTo办法,它能够直接将文件缓冲区的数据发送到方针Channel,避免了传统经过循环write办法导致的内存复制问题。

(三)引证计数与池化技能

1、在Netty中,每个被请求的Buffer关于Netty来说都或许是很名贵的资源,因而为了取得关于内存的请求与收回更多的控制权,Netty自己依据引证计数法去完结了内存的办理。

2、Netty关于Buffer的运用都是依据直接内存(DirectBuffer)完结的,大大提高I/O操作的功率

3、可是DirectBuffer和HeapBuffer比较之下除了I/O操作功率高之外还有一个天然生成的缺陷,即关于DirectBuffer的请求比较HeapBuffer功率更低

4、因而Netty结合引证计数完结了PolledBuffer,即池化的用法,当引证计数等于0的时分,Netty将Buffer收回致池中,鄙人一次请求Buffer的没某个时间会被复用。

六、总结

Netty其实本质上便是Reactor办法的完结,Selector作为多路复用器,EventLoop作为转发器,Pipeline作为事情处理器。

可是和一般的Reactor不同的是,Netty运用串行化完结,并在Pipeline中运用了职责链办法。

Netty中的buffer相对有NIO中的buffer又做了一些优化,大大提高了功用。

【粉丝福利】:

《架构师材料》收取办法

重视+转发,然后私信关键词 【架构】,即可获取。

二维码