每日一博 | 被“误解”的 Java AIO
为什么说 AIO 受”误解“,虽然这个”误解“被打上了双引号,但还是不得不承认它的发展状况并不好。AIO 是 Java 7 开始提供的新特性,而这个”新特性“到如今都成了陈年老酒还鲜有人去品味它。要知道 Java 7 可是在 2011年7月份发布的,市面上基于 AIO 实现的通信框架竟然寥寥无几,关于这项技术的介绍文章也普遍比较粗略。通过阅读那些介绍 AIO 的文章,似乎从学术层面大家就不怎么待见这项技术。
作为 AIO 的学习者、受益者,我觉得有必要先对网上的一些 ”偏见“ 表达一下自己的观点。如果能有幸在认知上搭成共识,之后的学习交流会更加顺畅一点。通常偏见源于比较,AIO 与 BIO、NIO 的对比明细如表所示。
BIO | NIO | AIO | |
---|---|---|---|
客户端 : I/O 线程数 | 1 : 1 | N : 1 | N : 0 |
I/O类型 | 同步阻塞 | 同步非阻塞 | 异步非阻塞 |
API使用难度 | 简单 | 复杂 | 一般 |
调试难度 | 简单 | 复杂 | 一般 |
可靠性 | 差 | 高 | 高 |
吞吐量 | 低 | 高 | 高 |
适用场景 | 适用于连接数量不多,并发量不高的场景。充分发挥易编程的优势。 | 适用于对连接数量以及稳定性、实时性有较高要求的场景,采用 NIO 或 AIO 能有效缓解网络 I/O 造成的机器负载。 | 同NIO |
误解一
通过上表的比较可以看出 AIO 的性价比应该是优于 NIO 的,而实际情况却是大多数人更偏爱与 NIO,准确的说应该是偏爱 NIO 通信框架:Netty。这本无可厚非,Netty 确实是一款非常优秀的项目,可是很多人错误的解读了 Netty 在 Github 上关于不支持 AIO 的理由,这更加遏制了 AIO 的发展。
Not faster than NIO (epoll) on unix systems (which is true)
这句话表达的本意应该是:NIO 和 AIO 在 unix 系统上使用的都是 epoll 模式,本质都是一样的。但Not faster than NIO
在一定程度上会让人误解为 AIO 没 NIO 快。 这里可以采用假设的方式来论证这个观点是不成立的。
假设:
epoll 表现的性能为 x=100;
通信框架因为要解决并发调度与资源分配问题,对 epoll 进行封装后会存在一定的性能损耗,以 y 表示。
最终性能表现结果应该是 r=x-y。
论证:
- 某款 NIO 框架基于 epoll 封装后的性能损耗值:y=5,则它所发挥的最终性能为:x-y=95。
- 如果有一款 AIO 框架能将性能损耗值控制在:y=(0,5) ,那最终性能便高于 NIO 框架。如 y>5,则性能低于 NIO 框架。
结论:
以底层模型是 kqueue、epoll、select 还是 IOCP 来比较 NIO 和 AIO 的性能是不严谨的,决定权在于框架实现能挖掘出多少基础能力。否则同样采用 NIO 技术,为什么不同的框架还是会有高低之分。
误解二
Linux 系统的 AIO 还不成熟。如果是这个原因的话,不妨先看下:http://lse.sourceforge.net/io/aio.html,其中核心的一句话:Support for kernel AIO has been included in the 2.6 Linux kernel.
请注意,Linux 内核自 2.6 版本起已支持AIO模式。
这是个很奇怪的现象,似乎曾经不支持 AIO 就觉得永远不支持,曾经出现的 bug 就永远存在。正如 JAVA NIO 的空轮训 bug ,如今都已经发展到 Java 13 了,依旧还有人坚信这个 bug 一直在。坦白的讲,我没有去验证过 Java AIO 在 Linux 环境下是否是真正意义的 AIO,也没有复现出 NIO 的空轮训 bug。但如果因为某种原因放弃持续学习,那对于事物的认知和见识就只能停留在过去。
所以”Linux 系统的 AIO 还不成熟“也不会成为我抛弃 AIO 的理由。
误解三
需要为每一个连接预先分配读缓存。这个确实是客观存在的情况,AIO 的使用方式是调用读写接口将ByteBuffer
对象注册进去,当事件完成后以回调的形式触发CompletionHandler
,所以必须要事先分配好缓存空间。
但是有一个细节可能会被大家忽略掉,即便采用 NIO,当遇到半包/粘包的的情况,还是需要有一个缓存对象来暂存这份不完整的数据。尤其在高并发场景下,半包/粘包现象很容易加剧,此时 NIO 需要分配的缓存并不比 AIO 节省多少。
即使假设理想状态下并不存在半包/粘包问题,AIO 通信的预分配形式又能额外消耗多少内存。为每个连接分配 1024 字节的读缓存,在1万个并发连接的条件下也才消耗不到 10MB 内存,试问现实场景下一台 Java 应用服务器需要同时支撑多少个并发,1万?5万?10万?。
目前已知的通信框架通常会配备内存池,在这种前提下 AIO 也只是将内存池中的资源提前利用起来而已。在同等的内存池配置,相同的并发压力下,如果 AIO 暴露出内存方面的问题,我们再来做 AIO 和 NIO 的选择。
总结
本文并不是要将 NIO 和 AIO 对立起来,这两项技术都非常吸引人,喜欢技术的朋友可以在这方面钻研很久。个人推荐纯粹出于学习优先考虑 NIO,因为难度更高,更具挑战性,将要面临和需要解决的问题更多。在学习的过程中如果遇到困惑,可以再去翻一下 AIO 的源码,里面有很多值得借鉴的设计。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Novel 1.2.2 发布,新增全屏显示
Novel v1.2.2 已发布,更新日志: 新增记住登录功能 新增全屏显示功能 新增api端下载初始化文档 调整layout组件单独分类 调整vuex模块化分类 调整服务监控页面进行自适应兼容 调整个人信息页面进行自适应兼容 修复操作日志查询问题 修复因字体 Helvetica 问题产生的文字高度不一致问题 其他问题修复 Novel简介 一直想做一款后台管理系统,看了很多优秀的开源项目,从中发现了若依开源框架,从她出现以来就一直关注,但发现其中的功能太过强大,部分功能也不太适合自己,并且自己也一直想要动手学习一下若依的强大之处,便有了自己现在的novel。 它可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。 内置功能 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 岗位管理:配置系统用户所属担任职务。 菜单管理:...
- 下一篇
谷歌在最高法院 API 版权诉讼中获得科技行业的支持
自 2010 年甲骨文起诉谷歌至今,谷歌和甲骨文之间的软件版权纠纷案(copyright dispute)已来来回回牵扯了十年之久。目前,该案件又有了新进展,据 ZDnet网站报道,在可以影响软件开发未来前景的谷歌对甲骨文的法律诉讼案中,一群科技公司和组织提供了对谷歌的支持。 科技行业认为,如果谷歌在与甲骨文的抗争中失败,行业中许多现有软件工程实践将会经历全面改革,同时,其创新的步伐也将受到拖延。 回顾事件可知,在 2018 年 3 月的最新一轮法律诉讼中,联邦巡回上诉法院认定 Android 侵权,判决甲骨文胜诉。但之后,谷歌并未就此罢休,并成功于 2019 年 11 月获得了美国最高法院(Supreme Court of the United States,SCOTUS)将对此次裁决的复审支持,重新思考甲骨文的胜诉一事。日前,谷歌还提醒美国最高法院称,甲骨文有可能成为垄断势力。 而在周一联合提交的,一份名为“friend of the court”的法律文件简报中,其又提供了一些相关信息表明:Mozilla,Medium,Cloudera,Reddit和其他人都一起呼吁 SCOTU...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS7设置SWAP分区,小内存服务器的救世主
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- Hadoop3单机部署,实现最简伪集群
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7安装Docker,走上虚拟化容器引擎之路