文档章节

受”误解“的Java AIO

三刀蜀黍
 三刀蜀黍
发布于 01/08 17:58
字数 1598
阅读 3875
收藏 30

为什么说 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。

论证:

  1. 某款 NIO 框架基于 epoll 封装后的性能损耗值:y=5,则它所发挥的最终性能为:x-y=95。
  2. 如果有一款 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 的源码,里面有很多值得借鉴的设计。

© 著作权归作者所有

三刀蜀黍

三刀蜀黍

粉丝 57
博文 7
码字总数 9695
作品 3
杭州
程序员
私信 提问
加载中

评论(23)

bastetwang
bastetwang
以前我也纠结于怎么没人用aio,后来找到linux内核网络部分一瞧,原来是没有实现...
bastetwang
bastetwang
这个现在不清楚了,但是linux的网络以前一直是不支持aio的,所以说以前用这个意义不大,(可能函数调用可以成功,这个要去看他的那个tcpip的那个挂上去的地方有没有实现那几个函数,如果没有就是不支持)
如果博主成功使用了,能不能贴一些benchmark出来。
斯武丶风晴
斯武丶风晴
深入底层指令,可以区分两种io的区别,再来讨论比较好
三刀蜀黍
三刀蜀黍 博主
底层的东西我不太懂,虽说网上介绍的文档不少,但copy的成分偏多。这篇文章就先从表象进行探讨,或许以后我知道的多了,会发现现在的有些观点是不准确的。
kidbei
kidbei
全靠猜啊…不严谨
dwingo
dwingo
我比较希望native层能把TCP的收发抽象成类似UDP的方式, 连接(session)的概念由上层来处理, 这样接口就非常简单了,即使用BIO也能很高效地处理大规模TCP连接. 当然顺序性,可靠性,握手/挥手的细节这些上层不关心的部分还是交给底层来处理.
三刀蜀黍
三刀蜀黍 博主
有想法可以行动起来了💪
dwingo
dwingo
每次都想到自己还没遇到榨干网络性能的需求, 就作罢了.😏 何况大规模网络连接的管理标准做法是用个高效的前端来扛, 后端只需一个或少量连接,用BIO都够了.
j
jungggle
这句话表达的本意应该是:NIO 和 AIO 在 unix 系统上使用的都是 epoll 模式,本质都是一样的。本意是这个吗?真读不出来
dwingo
dwingo
再补充一些:
4. JDK nio对epoll的封装也不是很高效, 有的实现(如netty,firenio)做了性能更好的epoll封装, 当然性能需要追求到这个级别的情况很少见.
5. BIO 也不要忽视, 连接数很少或者UDP服务器仍然可以选择BIO,不但性能不差,而且用起来非常简单.
dwingo
dwingo
我说说我了解的事实:
1. Linux上虽然提供了异步IO,但实际上JDK并没用上,无聊是nio还是aio都是调用epoll,其中aio封装的代码较多,所以在Linux上性能没有nio好是正常的(当然也不会差多少,通常可以忽略),说aio没有IO线程那是因为底层做了封装,否则epoll_wait操作是哪个线程做的?
2. aio在Windows上是封装了IOCP,而nio仍然只用传统的select,可想而知aio在Windows上能出色地发挥最佳效率.
3. 读缓存虽然总量也不太多,但越小越能发挥CPU缓存的优势,比直接读内存有数量级上的性能差距不可小看.
orpherus
orpherus
glibc的aio用的还是多线程模拟的,没有用上内核提供的aio接口
orpherus
orpherus
讲了这么多,倒是说说看,linux下的jdk支持不支持aio
Mark哥是我
Mark哥是我
我认为还是取舍的问题,aio可能比 nio更优秀,但是 nio的生态已经满足需求了,大家没有更大的兴趣继续去造AIO 的生态了,即使在今天,维护一个生态已经很不容易了。
使用J2SE进行服务器架构技术选型的变迁

虽然现在对大多数程序员来讲,基本不会再有使用Java开发一个服务器这样的任务,但是,这方面的技术研究一下,对自己的技术提高还是非常有帮助的。说不定啥时候能派上用场。 使用Java(J2SE)...

webas
2013/04/26
92
0
漫话:如何给女朋友解释什么是BIO、NIO和AIO?

周末午后,在家里面进行电话面试,我问了面试者几个关于IO的问题,其中包括什么是BIO、NIO和AIO?三者有什么区别?具体如何使用等问题,但是面试者回答的并不是很满意。于是我在面试评价中写...

漫话编程
2019/07/01
817
0
Android 开发者应该从 Java 转到 Kotlin 吗?谷歌告诉你

今年 I/O 大会上,谷歌宣布正在采取的下一个重大步骤是 Kotlin-first,Android 开发将越来越多地以 Kotlin 为主,许多新的 Jetpack API 和功能将首先在 Kotlin 中提供。并且当天谷歌就开源了...

h4cd
2019/05/13
10K
58
王垠:Kotlin 和 Checked Exception

最近 JetBrains 的 Kotlin 语言忽然成了热门话题。国内小编们传言说,Kotlin 取代了 Java,成为了 Android 的“钦定语言”,很多人听了之后热血沸腾。初学者们也开始注意到 Kotlin,问出各种...

程序师
2018/08/14
0
0
热闹背后的冷静思考:Kotlin 和 Checked Exception

本文转载自当然我在扯淡,原文《Kotlin 和 Checked Exception》,作者:王垠。文章转载已获授权。 最近 JetBrains 的 Kotlin 语言忽然成了热门话题。国内小编们传言说,Kotlin 取代了 Java,...

局长
2017/05/24
5.1K
90

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 谨以此文怀念逝去的人

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 今天没歌曲 手机党少年们想听歌,请使劲儿戳(这里) 今天是周六, 刚想开始写乱弹的时候, 翻到了巴叔新建的话题上, @ 巴拉迪维:宏哥,一路...

小小编辑
26分钟前
9
0
判断php变量是否定义,是否为空,是否为真的一览表

使用 PHP 函数对变量 $x 进行比较 表达式 gettype() empty() is_null() isset() boolean : if($x) $x = ""; string TRUE FALSE TRUE FALSE $x = null; NULL TRUE TRUE FALSE FALSE var $x; N......

Grayk
今天
12
0
服务器监控

1. 服务器监控内容有哪些? 答: 主要有服务监控 和 流量监控 2. 监控重点是? 答: 是 磁盘 和 流量,cpu是浮动的,意义不大 3. 怎样 实现 监控? 答:将 服务器 分为:监控者 和 被监管协议...

杨凯123
昨天
242
0
Apollo开发指南

一、准备工作 二、本地启动 2.1 Apollo Config Service和Apollo Admin Service 2.2 Apollo-Portal 2.3 Java样例客户端启动 2.4 .Net样例客户端启动 三、开发 3.1 Portal 实现用户登录功能 3....

Ciet
昨天
307
0
英文词汇 计算机网络中的专业英语单词及其缩写

学习计算机网络时,会阅读相关的专业文献。对于文献中经常出现的缩写形式的专业名词,做了一些积累。现于此博文中做个简单的分享,希望能对后来人有所帮助,平稳地入门计算机网络。 注:博文...

志成就
昨天
178
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部