Analysis of the principle of netty

InfoQ 2022-09-23 09:22:57 阅读数:671

analysisprinciplenetty
Netty简介
Netty是一个高性能、异步事件驱动的NIO框架,基于JAVA NIO提供的API实现.它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果. 作为当前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,一些业界著名的开源组件也基于Netty的NIO框架构建.
Netty线程模型
在JAVA NIO方面Selector给ReactorPatterns provide the foundation,Netty结合Selector和ReactorPatterns design an efficient threading model.先来看下Reactor模式:
2.1 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 request handlers.”.首先Reactor模式首先是事件驱动的,There are one or more concurrent input sources,有一个Server Handler和多个Request Handlers,这个Service HandlerThe incoming requests are multiplexed and distributed to the corresponding ones synchronouslyRequest Handler.可以如下图所示:
null
Structurally, it is somewhat similar to the producer and consumer model,i.e. one or more producers put events into oneQueue中,And one or more consumers actively from this queuepoll事件来处理;而Reactor模式则没有Queue来做缓冲,whenever an event is enteredService Handler之后,该Service HandlerWill take the initiative according to differentEvnent类型将其分发给对应的Request Handler来处理.
2.2 Reator模式的实现
关于Java NIO 构造Reator模式,Doug lea在《Scalable IO in Java》中给了很好的阐述,这里截取PPT对Reator模式的实现进行说明
1.The first implementation model is as follows:
null
这是最简单的Reactor单线程模型,由于Reactor模式使用的是异步非阻塞IO,所有的IONone of the operations are blocked,In theory a thread can handle all of them independentlyIO操作.这时Reactor线程是个多面手,负责多路分离套接字,Accept新连接,And dispatch the request to the processing chain.
对于一些小容量应用场景,A single-threaded model can be used.但对于高负载,大并发的应用却不合适,主要原因如下:
当一个NIO线程同时处理成百上千的链路,性能上无法支撑,即使NIO线程的CPU负荷达到100%,The message cannot be fully processed either
当NIO线程负载过重后,处理速度会变慢,Can cause a large number of client connections to time out,It is often retransmitted after a timeout,更加重了NIO线程的负载.
可靠性低,A thread unexpectedly loops infinitely,The entire communication system will be unavailable
为了解决这些问题,出现了Reactor多线程模型.
2.Reactor多线程模型:
null
compared to the previous model,This model employs multithreading in the processing chain part(线程池).
在绝大多数场景下,This model can meet the performance requirements.但是,in some special application scenarios,For example, the server will perform security authentication on the client's handshake message.这类场景下,单独的一个Acceptor线程可能会存在性能不足的问题.为了解决这些问题,产生了第三种Reactor线程模型
3.Reactor主从模型
null
This model is compared to the second model,是将Reactor分成两部分,mainReactor负责监听server socket,accept新连接;并将建立的socket分派给subReactor.subReactor负责多路分离已连接的socket,读写网络数据,对业务处理功能,其扔给worker线程池完成.通常,subReactor个数上可与CPU个数等同.
2.3 Netty模型
2.2finishedReactor的三种模型,那么Netty是哪一种呢?其实Netty的线程模型是Reactor模型的变种,那就是去掉线程池的第三种形式的变种,这也是Netty NIO的默认模式.Netty中ReactorThe participants of the pattern mainly have the following components:
Selector
EventLoopGroup/EventLoop
ChannelPipeline
Selector即为NIO中提供的SelectableChannel多路复用器,充当着demultiplexer的角色,这里不再赘述;The following two other functions and their existenceNetty之ReactorThe roles played in the mode are introduced.
3.EventLoopGroup/EventLoop
当系统在运行过程中,如果频繁的进行线程上下文切换,会带来额外的性能损耗.多线程并发执行某个业务流程,业务开发者还需要时刻对线程安全保持警惕,哪些数据可能会被并发修改,如何保护?这不仅降低了开发效率,也会带来额外的性能损耗.
为了解决上述问题,Netty采用了串行化设计理念,从消息的读取、编码以及后续Handler的执行,始终都由IO线程EventLoop负责,这就意外着整个流程不会进行线程上下文的切换,数据也不会面临被并发修改的风险.这也解释了为什么NettyThe threading model is removedReactorThread pool in master-slave model.
EventLoopGroup是一组EventLoop的抽象,EventLoopGroup提供next接口,Can be grouped togetherEventLoop里面按照一定规则获取其中一个EventLoop来处理任务,对于EventLoopGroupWhat needs to be understood here is inNetty中,在NettyWe need in server programmingBossEventLoopGroup和WorkerEventLoopGroup两个EventLoopGroup来进行工作.通常一个服务端口即一个ServerSocketChannel对应一个Selector和一个EventLoop线程,也就是说BossEventLoopGroup的线程数参数为1.BossEventLoop负责接收客户端的连接并将SocketChannel交给WorkerEventLoopGroup来进行IO处理.
EventLoop的实现充当Reactor模式中的分发(Dispatcher)的角色.
4.ChannelPipeline
ChannelPipelineActually in chargeReactorThe role of the request handler in the schema.
ChannelPipeline的默认实现是DefaultChannelPipeline,DefaultChannelPipelineitself maintains a user invisibletail和head的ChannelHandler,They are located at the head and tail of the linked list queue, respectively.tailin the upper part,而headin the direction close to the network layer.在Netty中关于ChannelHandler有两个重要的接口,ChannelInBoundHandler和ChannelOutBoundHandler.inboundIt can be understood that network data flows from the outside to the inside of the system,而outboundIt can be understood that network data flows from the inside of the system to the outside of the system.用户实现的ChannelHandlerOne or more of these interfaces can be implemented as needed,将其放入Pipelinein the linked list queue,ChannelPipeline会根据不同的IOevent type to find the correspondingHandler来处理,At the same time, the linked list queue is a variant of the chain of responsibility pattern,Top-down or bottom-up all satisfy event correlationHandlerevents are processed.
ChannelInBoundHandler对从客户端发往服务器的报文进行处理,Generally used to perform half-packages/粘包,解码,读取数据,业务处理等;ChannelOutBoundHandler对从服务器发往客户端的报文进行处理,一般用来进行编码,发送报文到客户端.
下图是对ChannelPipeline执行过程的说明:
null
netty原理分析
关于PipelineFor more information, please refer to:浅谈管道模型(Pipeline)
5.Buffer
Nettyprovided expandedBuffer相对NIOhas many advantages,As a very important piece of data access,我们来看看Netty中的Buffer有什么特点.
1.ByteBuf读写指针
在ByteBuffer中,读写指针都是position,而在ByteBuf中,The read and write pointers are respectivelyreaderIndex和writerIndex,直观看上去ByteBufferOnly one pointer is used to achieve the function of two pointers,Variables are saved,But when forByteBufferIt must be called when the read and write status of the switch is switchedflip方法,And before the next write,必须要将BuffeRead the content in,再调用clear方法.Called before each readflip,写之前调用clear,This undoubtedly brings tedious steps to the development,And the content cannot be written until it has been read,这样非常不灵活.Let's see in comparisonByteBuf,Just rely on when readingreaderIndex指针,Just rely on when writingwriterIndex指针,There is no need to call the corresponding method before each read and write,And there is no limit to having to read it all at once.
2.零拷贝
Netty的接收和发送ByteBuffer采用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝.如果使用传统的堆内存(HEAP BUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中.相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝.
Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer.
Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题.
3.Reference counting and pooling techniques
在Netty中,each appliedBuffer对于Nettycan be a valuable resource,Therefore, in order to gain more control over the application and recycling of memory,NettyIt implements memory management according to the reference counting method.Netty对于BufferThe usage is based on direct memory(DirectBuffer)实现的,大大提高I/O操作的效率,然而DirectBuffer和HeapBufferExcept by comparisonI/OIn addition to the high operational efficiency, there is an inherent disadvantage,即对于DirectBuffercompared to applicationsHeapBuffer效率更低,因此NettyCombined with reference counting to achievePolledBuffer,That is, the usage of pooling,当引用计数等于0的时候,Netty将BufferRecycled into the pool,Apply next timeBufferwill be reused at no time.
总结
Netty其实本质上就是Reactor模式的实现,Selector作为多路复用器,EventLoop作为转发器,Pipeline作为事件处理器.但是和一般的Reactor不同的是,NettyUse serialization,并在PipelineThe Chain of Responsibility pattern is used.
Netty中的buffer相对有NIO中的buffer又做了一些优化,大大提高了性能.
为了让学习变得轻松、高效,今天给大家免费分享一套阿里架构师传授的一套教学资源.帮助大家在成为架构师的道路上披荆斩棘.这套视频课程详细讲解了(Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构)等这些成为架构师必备的内容!而且还把框架需要用到的各种程序进行了打包,根据基础视频可以让你轻松搭建分布式框架环境,像在企业生产环境一样进行学习和实践.
1、具有1-5工作经验的,面对目前流行的技术不知从何下手,
需要突破技术瓶颈的.2、在公司待久了,过得很安逸,
但跳槽时面试碰壁.需要在短时间内进修、跳槽拿高薪的.
3、如果没有工作经验,但基础非常扎实,对java工作机制,
常用设计思想,常用java开发框架掌握熟练的.
4、觉得自己很牛B,一般需求都能搞定.
但是所学的知识点没有系统化,It is difficult to continue to break through in the technical field.
5. v号:xiaoyanya_1获取哦,或者
点击链接免费获取
null


版权声明:本文为[InfoQ]所创,转载请带上原文链接,感谢。 https://javamana.com/2022/266/202209230910157522.html