Netty实现原理分析
Netty简介
Netty是高性能、异步事件驱动的NIO框架 基于Java NIO提供的API实现
提供了对TCP、UDP和文件传输的支持
Netty所有IO操作都是异步非阻塞的 通过Future-Lisener机制 用户可以方便的主动获取或者通过通知机制获得IO操作结果
广泛应用互联网领域、大数据分布式计算领域、游戏行业、通信行业
Netty线程模型
Netty结合Java NIO的Selector和Reactor模式设计了高效的线程模型
Reactor模式
基于事件驱动
有一个或多个并发输入源
一个Server Handler
多个Request Handlers
每当一个事件输入到Service Handler之后,该Service Handler会主动根据不同的Evnent类型将其分发给对应的Request Handler来处理
Reactor模式实现
Reactor单线程模型
1、一个线程可以独立处理所有的IO操作2、既负责多路分离套接字又Accept新连接又并分发请求到处理链中3、一些小容量应用场景,可以使用到单线程模型
但对于高负载,大并发的应用却不合适 原因是
当一个NIO线程同时处理成百上千的链路,性能上无法支撑,即使NIO线程的CPU负荷达到100%,也无法完全处理消息
当NIO线程负载过重后,处理速度会变慢,会导致大量客户端连接超时,超时之后往往会重发,更加重了NIO线程的负载。
可靠性低,一个线程意外死循环,会导致整个通信系统不可用
Reactor多线程模型
该模型可以解决上述问题
该模型在处理链部分采用了多线程(线程池)
绝大多数场景下,该模型都能满足性能需求
但在一些特殊的应用场景下,如服务器会对客户端的握手消息进行安全认证这类场景下,单独的一个Acceptor线程可能会存在性能不足的问题为了解决这些问题,产生了第三种Reactor线程模型
Reactor主从模型
a、Reactor分成两部分 mainReactor负责监听server socket、accept新连接 并将建立的socket分派给subReactorb、subReactor负责多路分离已连接的socketc、worker线程池完成读写网络数据,对业务处理功能d、subReactor个数上可与CPU个数等同
弊端
当系统在运行过程中,频繁的进行线程上下文切换,会带来额外的性能损耗
要考虑多线程安全问题
Netty模型
Netty线程模型去掉了Reactor主从模型中线程池
为了解决上述问题
Netty采用了串行化设计理念
从消息的读取、编码以及后续Handler的执行始终都由IO线程EventLoop负责这就意外着整个流程不会进行线程上下文的切换数据也不会面临被并发修改的风险
核心组件
Selector
Selector即为NIO中提供的SelectableChannel多路复用器充当着demultiplexer的角色
EventLoopGroup/EventLoop
EventLoop的实现充当Reactor模式中的分发(Dispatcher)的角色
EventLoopGroup是一组EventLoop的抽象 EventLoopGroup提供next接口
从一组EventLoop里面按照一定规则获取其中一个EventLoop来处理任务
对于EventLoopGroup这里需要了解的是在Netty中 在Netty服务器编程中需要BossEventLoopGroup和WorkerEventLoopGroup两个EventLoopGroup来进行工作
通常一个服务端口即一个ServerSocketChannel对应一个Selector和一个EventLoop线程,也就是说BossEventLoopGroup的线程数参数为1
BossEventLoop负责接收客户端的连接并将SocketChannel交给WorkerEventLoopGroup来进行IO处理
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对从服务器发往客户端的报文进行处理,一般用来进行编码,发送报文到客户端
Buffer
ByteBuf读写指针
在ByteBuffer中,读写指针都是position而在ByteBuf中,读写指针分别为readerIndex和writerIndex直观看上去ByteBuffer仅用了一个指针就实现了两个指针的功能,节省了变量但是当对于ByteBuffer的读写状态切换的时候必须要调用flip方法而当下一次写之前,必须要将Buffe中的内容读完,再调用clear方法每次读之前调用flip,写之前调用clear,这样无疑给开发带来了繁琐的步骤而且内容没有读完是不能写的,这样非常不灵活相比之下我们看看ByteBuf读的时候仅仅依赖readerIndex指针,写的时候仅仅依赖writerIndex指针不需每次读写之前调用对应的方法而且没有必须一次读完的限制
零拷贝
1、Netty的接收和发送ByteBuffer采用DIRECT BUFFERS使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝如果使用传统的堆内存(HEAP BUFFERS)进行Socket读写JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。
2、Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象用户可以像操作一个Buffer那样方便的对组合Buffer进行操作避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的BufferNetty的文件传输采用了transferTo方法它可以直接将文件缓冲区的数据发送到目标Channel避免了传统通过循环write方式导致的内存拷贝问题。
引用计数与池化技术
在Netty中,每个被申请的Buffer对于Netty来说都可能是很宝贵的资源因此为了获得对于内存的申请与回收更多的控制权Netty自己根据引用计数法去实现了内存的管理
Netty对于Buffer的使用都是基于直接内存(DirectBuffer)实现的大大提高I/O操作的效率然而DirectBuffer和HeapBuffer相比之下除了I/O操作效率高之外还有一个天生的缺点
即对于DirectBuffer的申请相比HeapBuffer效率更低因此Netty结合引用计数实现了PolledBuffer,即池化的用法当引用计数等于0的时候 Netty将Buffer回收致池中在下一次申请Buffer的没某个时刻会被复用
总结
Netty其实本质上就是Reactor模式的实现Selector作为多路复用器,EventLoop作为转发器,Pipeline作为事件处理器但是和一般的Reactor不同的是,Netty使用串行化实现,并在Pipeline中使用了责任链模式
Netty实现原理分析相关推荐
- 【Netty】原理分析:ChannelHandlerContext
上面一篇文章介绍了 ChannelPipeline,它维护了一个有序的 ChannelHandler 列表.当 ChannelHandler 加入到 ChannelPipeline 的时候,会创建一个 ...
- Netty时间轮调度原理分析,再不了解你就out啦
一.时间轮介绍 之前公司内部搭建的延迟队列服务有用到时间轮,但是一直没有了解过它的实现原理. 最近有个和支付宝对接的项目,支付宝接口有流量控制,一定的时间内只允许 N 次接口调用,针对一些业务我们需要 ...
- Netty技术细节源码分析-Recycler对象池原理分析
本文是该篇的修正版 本文的github地址:点此 该文所涉及的netty源码版本为4.1.6. Netty的对象池Recycler是什么 Recycler是Netty中基于ThreadLocal的轻量 ...
- 原理剖析(第 012 篇)Netty之无锁队列MpscUnboundedArrayQueue原理分析
原理剖析(第 012 篇)Netty之无锁队列MpscUnboundedArrayQueue原理分析 - 一.大致介绍 1.了解过netty原理的童鞋,其实应该知道工作线程组的每个子线程都维护了一个任 ...
- 「Netty系列」使用wireshark对网络通信扑捉,进行三次握手和四次挥手原理分析(Netty前置二)
正常下班,文章走起.在网络的通信的时候,都有听说过三次握手四次挥手.但是对其原理是否清晰?本篇文章通过使用wireshark对网络通信扑捉,进行原理分析. 1 BIO代码实现 //服务端代码 publ ...
- Netty实现原理浅析
为什么80%的码农都做不了架构师?>>> 1.总体结构 先放上一张漂亮的Netty总体结构图,下面的内容也主要围绕该图上的一些核心功能做分析,但对如Container Inte ...
- [强烈推荐] 新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析
新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析 1.引言 Netty 是一个广受欢迎的异步事件驱动的Java开源网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 本文基 ...
- Netty源码分析系列之常用解码器(下)——LengthFieldBasedFrameDecoder
扫描下方二维码或者微信搜索公众号菜鸟飞呀飞,即可关注微信公众号,Spring源码分析和Java并发编程文章. 前言 在上一篇文章中分析了三个比较简单的解码器,今天接着分析最后一个常用的解码器:Leng ...
- 【Java进阶营】【Kafka技术专题】核心技术原理分析和介绍
[Kafka简介] ** Kafka是一种分布式的,基于发布/订阅的消息系统,它可以让你发布和订阅记录流.在这方面,它类似于一个消息队列或企业消息系统.它可以让你持久化收到的记录流,从而具 ...
最新文章
- ViewPager单页显示3个item
- webwork2.2.4+spring配制方式总结
- 《ASCE1885的信息安全》の使用Crypto++的MD5算法对字符串进行哈希
- 猫狗分类--Tensorflow实现
- python3九九乘法表儿歌下载_Python3基础 九九乘法表
- P2475 [SCOI2008]斜堆(递归模拟)
- STM32工作笔记0039---认识电路图中的DS203,MS,L等
- window下spark的安装和开发环境配置
- IIS 部署的网站无法启动
- Druid连接池简介和配置
- UI :新手自学完全指南(1) Karen X. Cheng
- C语言------内存管理
- 系统架构设计知识梳理--分布式架构
- gen阻抗 pcie_PCIe Gen3/Gen4接收端链路均衡测试(上篇:理论篇)
- Jetson-Xavier-NX使用教程(这里说插上烧好镜像的SD卡上电就可以直接用了)
- hive安装过程中报错处理办法
- 2.Elasticsearch集群实现
- (附源码)小程序 社区居家养老互助服务管理平台 毕业设计 062027
- S3C6410开发(1)-初步入门
- Exchange2016 更换见证服务器