30-深入Hotspot源码与Linux内核理解NIO/BIO/AIO

news2024/9/29 5:39:02

IO模型
IO模型就是说用什么样的通道进行数据的发送和接收,Java共支持3种网络编程IO模式:BIO,NIO,AIO

BIO(Blocking IO)
同步阻塞模型,一个客户端连接对应一个处理线程
在这里插入图片描述
缺点:
1、IO代码里read操作是阻塞操作,如果连接不做数据读写操作会导致线程阻塞,浪费资源
2、如果线程很多,会导致服务器线程太多,压力太大,比如C10K问题
应用场景:
BIO 方式适用于连接数目比较小且固定的架构, 这种方式对服务器资源要求比较高, 但程序简单易理解。

NIO(Non Blocking IO)
同步非阻塞,服务器实现模式为一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到多路复用器selector上,多路复用
器轮询到连接有IO请求就进行处理,JDK1.4开始引入。
应用场景:
NIO方式适用于连接数目多且连接比较短(轻操作) 的架构, 比如聊天服务器, 弹幕系统, 服务器间通讯,编程比较复杂
总结:
如果连接数太多的话,会有大量的无效遍历,假如有10000个连接,其中只有1000个连接有写数据,但是由于其他9000个连接并没有断开,我们还是要每次轮询遍历一万次,其中有十分之九的遍历都是无效的,这显然不是一个让人很满意的状态。

NIO 有三大核心组件: Channel(通道), Buffer(缓冲区),Selector(多路复用器)
1、channel 类似于流,每个 channel 对应一个 buffer缓冲区,buffer 底层就是个数组
2、channel 会注册到 selector 上,由 selector 根据 channel 读写事件的发生将其交由某个空闲的线程处理
3、NIO 的 Buffer 和 channel 都是既可以读也可以写

在这里插入图片描述
NIO底层在JDK1.4版本是用linux的内核函数select()或poll()来实现,跟上面的NioServer代码类似,selector每次都会轮询所有的sockchannel看下哪个channel有读写事件,有的话就处理,没有就继续遍历,JDK1.5开始引入了epoll基于事件响应机制来优化NIO。

NioSelectorServer 代码里如下几个方法非常重要,我们从Hotspot与Linux内核函数级别来理解下

Selector.open() //创建多路复用器
socketChannel.register() //将channel注册到多路复用器上
selector.select() //阻塞等待需要处理的事件发生

在这里插入图片描述
总结:
NIO整个调用流程就是Java调用了操作系统的内核函数来创建Socket,获取到Socket的文件描述符,再创建一个Selector对象,对应操作系统的Epoll描述符,将获取到的Socket连接的文件描述符的事件绑定到Selector对应的Epoll文件描述符上,进行事件的异步通知,这样就实现了使用一条线程,并且不需要太多的无效的遍历,将事件处理交给了操作系统内核(操作系统中断程序实现),大大提高了效率。

Epoll函数详解

int epoll_create(int size);

创建一个epoll实例,并返回一个非负数作为文件描述符,用于对epoll接口的所有后续调用。参数size代表可能会容纳size个描述符,但size不是一个最大值,只是提示操作系统它的数量级,现在这个参数基本上已经弃用了。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

使用文件描述符epfd引用的epoll实例,对目标文件描述符fd执行op操作。
参数epfd表示epoll对应的文件描述符,参数fd表示socket对应的文件描述符。
参数op有以下几个值:
EPOLL_CTL_ADD:注册新的fd到epfd中,并关联事件event;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中移除fd,并且忽略掉绑定的event,这时event可以为null;
参数event是一个结构体

struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};

typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;

events有很多可选值,这里只举例最常见的几个:
EPOLLIN :表示对应的文件描述符是可读的;
EPOLLOUT:表示对应的文件描述符是可写的;
EPOLLERR:表示对应的文件描述符发生了错误;
成功则返回0,失败返回-1

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

等待文件描述符epfd上的事件。
epfd是Epoll对应的文件描述符,events表示调用者所有可用事件的集合,maxevents表示最多等到多少个事件就返回,
timeout是超时时间。

I/O多路复用底层主要用的Linux 内核函数(select,poll,epoll)来实现,windows不支持epoll实现,windows底层是基于winsock2的
select函数实现的(不开源)
在这里插入图片描述
Redis线程模型
Redis就是典型的基于epoll的NIO线程模型(nginx也是),epoll实例收集所有事件(连接与读写事件),由一个服务端线程连续处理所有事件命令。
Redis底层关于epoll的源码实现在redis的src源码目录的ae_epoll.c文件里,感兴趣可以自行研究。

AIO(NIO 2.0)
异步非阻塞, 由操作系统完成后回调通知服务端程序启动线程去处理, 一般适用于连接数较多且连接时间较长的应用
应用场景:
AIO方式适用于连接数目多且连接比较长(重操作)的架构,JDK7 开始支持

BIO、 NIO、 AIO 对比:
在这里插入图片描述
为什么Netty使用NIO而不是AIO?
在Linux系统上,AIO的底层实现仍使用Epoll,没有很好实现AIO,因此在性能上没有明显的优势,而且被JDK封装了一层不容易深度优化,Linux上AIO还不够成熟。Netty是异步非阻塞框架,Netty在NIO上做了很多异步的封装。

同步异步与阻塞非阻塞(段子)
老张爱喝茶,废话不说,煮开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 老张把水壶放到火上,立等水开。(同步阻塞)
老张觉得自己有点傻
2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
3 老张把响水壶放到火上,立等水开。(异步阻塞)
老张觉得这样傻等意义不大
4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
老张觉得自己聪明了。

所谓同步异步,只是对于水壶而言。
普通水壶,同步;响水壶,异步。
虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。
同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。
所谓阻塞非阻塞,仅仅对于老张而言。
立等的老张,阻塞;看电视的老张,非阻塞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/129025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spreadsheet与FineReport数据集对比

什么是数据集?在BI工具中指的是在报表开发前的取数过程,把需要的数据整合成一个数据集合,以便于在报表开发中使用。可以把它理解为我们基于数据库获取我们需要的数据。而数据库获取数据是有多种方式的,比如可以通过直接写SQL语句、…

基于verilog实现序列相关检测

题目来源牛客网,完整工程源码:https://github.com/ningbo99128/verilog 目录 1、VL25 输入序列连续的序列检测 题目介绍 思路分析 代码实现 仿真文件 2、VL26 含有无关项的序列检测 题目介绍 思路分析 代码实现 仿真文件 3、VL27 不重叠序列检…

Sleuth+Zipkin架构

为什么要链路追踪 小结: nacos 【name server】:注册中心,解决服务的注册与发现 nacos【config】:配置中心,微服务配置文件的中心化管理,同时配置信息的动态刷新 Ribbon:客户端负载均衡器&#…

《设计模式》享元模式

《设计模式》享元模式《设计模式》设计模式的基本原则 《设计模式》单例模式 《设计模式》工厂模式 《设计模式》原型模式 《设计模式》建造者模式 《设计模式》适配器模式 《设计模式》桥接模式 《设计模式》装饰者模式 《设计模式》组合模式 《设计模式》外观模式 《设计模式…

数据结构课设:迷宫问题

文章目录前言一、概要设计1、基本信息2、功能模块图3、功能描述4、调用关系图5、结果演示① 创建迷宫② 求解③ 清除多余路径二、完整代码前言 最近刚好在写自己的课设,匆匆忙忙写出来的课设系统,仍有不足,拿出来和大家分享一下,…

C. p-binary(二进制位)

Problem - 1225C - Codeforces Vasya会看中任何数字,只要它是2的整数次方。另一方面,Petya非常保守,只喜欢单一的整数p(可以是正数、负数或零)。为了结合他们的口味,他们发明了2xp形式的p-二进制数&#xf…

jmeter接口测试之导入测试用例/get请求中Url存在参数(工作日记2)

导入接口用例进行接口测试 以运营中心测试计划中的企业菜单管理为例 【前提条件】 1、有接口数据 2、有接口用例 我们需要把接口测试用例转换为CSV格式步骤如下: 右键选择打开方式为Notepad 需要将文件设置一下编码 文件留着备用 【步骤】 1、新建一个企业…

前端基础之PS和相关基础知识总结

PS安装: 淘宝 PS简介 面板简介(菜单栏、工具栏、辅助面板) 图片格式: jpgjpeg(色彩丰富的图片)png(半透明图片)gif(网页动态图)psd(ps设计源文…

android java udp广播 用于局域网搜索扫描设备。

DatagramSocket socket new DatagramSocket();//设置接收等待时长socket.setSoTimeout(LanCommConfig.RECEIVE_TIME_OUT);byte[] sendData new byte[1024];//使用广播形式(目标地址设为255.255.255.255)的udp数据包DatagramPacket sendPacket new Dat…

STC15单片机+DS18B20+LCD1602+PCF8574转IIC接口温度显示

STC15单片机+DS18B20+LCD1602+PCF8574转IIC接口温度显示 📺显示效果 LCD1602 IIC接口 ✨本示例基于自制的STC开发板,主控采用的:IAP15W4K61S4相关篇《【PCB开源分享】STC/IAP15W4K61S4开发板》《【开源分享】自制STC15W408AS开发板》🌼接线说明 🌿CD1602+PCF8574转IIC接…

stlink下载调试器使用说明(STM32采用stlink下载程序)

stlink能干什么? 最基本的功能:下载程序。 一般STM32支持ISP串口下载,也支持stlink、jlink等下载器下载 。 使用stlink、jlink下载要比串口方便很多,在keil里直接点击下载就行了,不需要去选择hex文件,速度…

你可能还不知道 golang 的高效编码细节

xdm,我们都知道 golang 是天生的高并发,高效的编译型语言 可我们也都可知道,工具再好,用法不对,全都白费,我们来举 2 个常用路径来感受一下 struct 和 map 用谁呢? 计算量很小的时候&#xf…

特斯拉第10000桩落成,百度地图送10000名充电免单!

「导语」 为庆祝特斯拉在中国大陆落成第10000个超级充电桩,百度地图推出特斯拉车主专属权益。车主们通过百度地图APP,即可实时获取超级充电桩空闲信息、一键规划专属充电路线。12.28-1.2期间,更有10000份充电免单福利限时放送。 在汽车电动…

Linux环境开机自启java应用

Linux环境设置开机自启java应用(Linux定时任务) crontab是Unix和Linux用于设置需要周期性被执行的指令,是Linux服务器很常用的技术,很多任务都会设置在crontab循环执行。 crontab : 提供给用户控制任务计划的命令&…

WebDAV之葫芦儿·派盘+File Manager

File Manager 支持WebDAV方式连接葫芦儿派盘。 手机文件太多,空间不足、隐藏文件多、文件清理不干净?推荐您一个功能强大的文件管理器,可以让你对手机中的各类文件进行管理,支持快速移动、复制粘贴、压缩解压等等。同时还能对已经安装的程序进行卸载,自动识别手机中的AP…

啥牌子的蓝牙耳机音质好?2023公认音质最好的蓝牙耳机

音乐是有魔力的,繁杂的工作和琐碎的生活,使得大多数人焦虑不安,音乐可以令人放松,蓝牙耳机越多越多,真不知道怎么挑好,品牌成百上千,款式就更不用说了,下面笔者专门整理了一期音质表…

【小西】优化生日品同步网易严选功能,使其支持多SPU对多SKU关系

目录前言思路代码实现实体ThemeActivityGift:spuId由 String类型变为JSONArrayThemeActivityGiftServiceImpl改造handleYxGiftByOperation:保存的是严选的生日品checkSpuIds:校验SPU有效性checkSpuIdExist:校验单个spuId是否存在c…

C语言函数栈帧的创建和销毁

前期学习的时候,我们可能有很多困惑,比如: 局部变量是怎么创建的? 为什么局部变量的值是随机值? 函数是怎么传参的?传参的顺序是怎样的? 形参和实参是什么关系? 函数调用是怎么…

分享丨品牌零售行业三大实践解读,全面搭建并落地数字化运营体系

以下内容来自神策数据创始人 & CEO 桑文锋关于数据驱动零售品牌业务增长的相关分享。点击文末“阅读原文”,了解神策品牌零售行业完整版解决方案。神策从 2020 年深入品牌零售领域,一路走来跌跌撞撞,不过思路越来越清晰,对该领…

Echarts:饼图默认高亮和选中(突出并高亮)/添加单击事件/X轴字符标签换行处理

饼图默认高亮: // 我这里实现的是饼图// 获取 this.sysfbChart this.$echarts.init(document.getElementById(sysfb))// 默认高亮第一个 // highlight:突出 this.sysfbChart.dispatchAction({type: highlight,seriesIndex: 0,dataIndex: 0}); 效果图: 饼图选中(突出并高亮):…