当前位置: 首页 > news >正文

从BIO,NIO到多路复用IO——认识Netty框架

同步

简单来说,同步是一种可靠的有序运行机制,当我们进行同步操作时,后续的任务是等待当前调用返回,才会进行下一步。
在IO模型中,如果程序本身去进行系统调用并且等待系统调用完成后执行IO读取操作,这就是同步,与IO读取后是否开启新线程进行业务操作无关。所以无论是BIO,NIO还是多路复用都属于同步IO模型。

BIO(Block IO)和PIO(伪异步)

BIO即同步阻塞IO。专门有一个线程(accept),负责监听客户端的请求。只要有客户端和服务端建立了一个请求,创建一个新的线程来处理。每个连接必须要开一个线程来处理,并且没有处理完线程不退出。

PIO就是在BIO的基础上引入了线程池,每次从线程池中选择线程来处理请求,减少了频繁创建和销毁线程的性能消耗。

在连接数不多的情况下,传统IO编写容易使用。但是随着连接数的增多,传统的IO就不行了

NIO (Non-Block IO)

同步非阻塞,在BIO中默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK,即accept方法非阻塞,有数据就处理没数据就跳过。这种方式就不需要每个连接创建一个线程来处理,通过轮询就可以处理多个连接。

NIO的缺点:

NIO相对BIO而言避免了多线程问题,但是由于程序中无法判断IO是否准备就绪,所以仍然只能遍历所有连接的fd进行accept或recv系统调用,复杂度是O(n),程序进行系统调用的accept和recv操作涉及到用户态和内核态的转换,所以频繁的系统调用是的性能也受影响,著名的C10K问题

多路复用IO(Select,Poll,EPoll)

多路复用器解决了IO状态判断的问题通过系统调用得到IO可用状态的fds集合,多路复用的模型本质上仍然都是同步 IO。

Select

同时监听多个fd,把所有连接描述符一次性发送给select系统调,阻塞等待系统调用返回IO状态结果集,程序遍历返回结果集合有针对性地对fds进行读写调用,这种方式减少了那些因无法判断IO状态而进行的不必要的accept和recv操作的次数,从而避免了用户态到内核态的频繁切换,提高了性能。

但是select系统调用存在fds个数限制,默认最多是1024。

Poll

与select类似,唯一区别是没有使用fdset而是pollset,对fd的个数没有限制

select、poll的缺点:

  • 把fd的监听列表放在用户空间,由用户空间管理,每次通过系统调用判断IO状态时都需要将fd的set集合从用户空间复制到和内核空间
  • 每次执行系统调用 都需要遍历整个fd的set集合进行IO状态判断,执行效率会随着fdset的增大而线性下降。

EPoll

基于select和poll的缺点,epoll的出现解决了这些问题,epoll可以理解为Event Poll。

对于每一个新创建的连接而言,程序通过调用epoll_create系统调用创建指定连接的fd标识,然后通过epoll_ctl系统调用把fd标识add到内核空间,这两个操作在连接的生命周期中只执行一次。EPoll模型中会给每个监听的fd增加一个回调函数,当IIO就绪状态时将fd放入就绪列表中,用户程序只需要通过epoll_wait系统调用从就绪列表中获取就绪的fd进行IO操作即可。

  • 需要将fd从用户态复制到内核态,使用MMAP共享内存映射实现。
  • 有fd内核事件时,通过回调把该fd放到就绪队列中,应用程序不需要每次传递所有的fd执行系统调用获取IO状态。

  • 没有fd限制,1g内存可以处理10w个fd

Netty

Netty是由JBOSS提供的一个java开源框架。也就是说,Netty 是一个基于EPoll模型实现的的客户、服务器端编程框架。

Netty 抽象出两组EventLoopGroup类型的线程池, 一个是BossGroup专门负责接收客 户端连接,一个是WorkerGroup专门负责网络读写操作。

在每个线程组中存在多个NioEventLoop,表示一个不断循环执行处理 任务的线程;每个 NioEventLoop 都有一个selector,用于监听绑定在其上的 socket 网络通道。初始化线程组时,如果不指定参数的话NioEventLoop的数量默认情况下是当前COU核数*2,客户端会被依次分配给空闲的NioEventLoop。例如在4核CPU中启动server后,依次启动10个客户端,对应会分配给WorkGroup中的1-8的WorkGroup,最后两个重新分配给1和2

连接请求到BossGroup中,NioEventLoop不断轮询accept接受新连接创建NioSocketChannel,然后把NioSocketChannel注册到WorkerGroup中的某个NioEventLoop中的selector上。WorkerGroup中的NioEventLoop负责轮询执行IO操作, NioEventLoop 内部采用串行化设计, 从消息的读取->解码->处理->编码->发送, 始终由 IO 线 程 NioEventLoop 负责。

大部分的javaweb应用都是基于Servlet容器(tomcat)实现的Http服务,但是当并发或者性能需要改善时,我们就可以考虑采用基于NIO网络模型的Netty来实现HTTP服务,以此提高性能和吞吐量,Netty内置了HTTP相关的编解码器,让用户可以很方便的开发出高性能的HTTP协议的服务,Spring Webflux默认是使用的Netty。例如基于Webflux的springcloud gateway默认就是自己与netty的,不需要其他web容器

http://www.jsqmd.com/news/615278/

相关文章:

  • 【国家级数字农场认证标准】:PHP可视化配置合规性检查清单(含GDPR+农业农村部2024新规适配)
  • OctoPi性能优化:7个技巧提升打印质量和速度
  • Browser.html开发环境配置:Node.js、Servo和Electron客户端详解
  • 从零开始手搓一个STM32与机智云的小项目——GPIO的输入输出
  • DeepTutor学习社区:与其他学习者交流经验的终极指南
  • Blazor WebAssembly性能突破:实测冷启动<80ms、首屏加载<300ms的7项高级优化技法(含源码级Hook方案)
  • ESPS USB MSC 调试全过程记录栽
  • RangeSeekBar测试策略:单元测试和UI自动化测试完整方案
  • rapidocr v3.8.0发布了
  • 终极指南:如何用虎符台Legion Seal轻松管理你的全面战争MOD
  • 体系结构论文(九十八):NPUEval: Optimizing NPU Kernels with LLMs and Open Source Compilers
  • openwrt在allwinner r328平台开启5G WIFI AP
  • 0.DJI-PSDK开发准备及资料说明(基于DJI经纬M300RTK和M350RTK无人机上使用)
  • 联发科MTK专用刷机提取工具|免引导文件直提原厂固件包|支持安卓4-11全平台救砖与系统刷写
  • PHP + CodeLlama + 自研规则引擎:构建企业级AI代码审查流水线(附GitHub开源配置模板)
  • Calico IPIP 使用指南章
  • NFC Tool 免vip,使用联动密钥破解加密门禁卡教程
  • ThreadlessInject终极指南:掌握无线程进程注入的完整教程
  • Lua语法详解:从变量声明到循环遍历的避坑指南
  • 如何完整破解Cursor Pro功能限制:一键激活与无限使用的终极指南
  • 终极指南:5分钟快速配置OpenTabletDriver开源数位板驱动
  • 为什么选择Mobile Native Foundation:大规模移动应用开发的完整解决方案终极指南
  • LANs.py代码实现原理:深入理解nfqueue与Scapy的协同工作机制
  • 将盾CDN:安全运营中心建设的实战经验
  • Goreman性能优化:提升多进程管理效率的10个最佳实践
  • 突破音乐加密壁垒:Unlock Music的技术创新与实践指南
  • 一个0基础的人怎么开始学AI?(不说废话)
  • Lua语法进阶:函数封装与条件控制的艺术
  • 终极Windows风扇控制解决方案:FanControl深度配置与性能优化实战指南
  • 3分钟开启浏览器编程:Core72在线IDE零配置开发指南 [特殊字符]