为何说 AIO 受”误解“,虽然这个”误解“被打上了双引号,但仍是不得不认可它的发展情况并很差。AIO 是 Java 7 开始提供的新特性,而这个”新特性“到现在都成了陈年老酒还鲜有人去品味它。要知道 Java 7 但是在 2011年7月份发布的,市面上基于 AIO 实现的通讯框架居然寥寥无几,关于这项技术的介绍文章也广泛比较粗略。经过阅读那些介绍 AIO 的文章,彷佛从学术层面你们就不怎么待见这项技术。html
做为 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。高并发
论证:性能
结论:
以底层模型是 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 的源码,里面有不少值得借鉴的设计。