选型上可以直接说结论:**生产环境基本不用裸 NIO,更用不上 AIO——要么用 Netty(NIO 封装),要么 JDK 21 虚拟线程跑 BIO 风格的代码**。这篇的模型对比讲得很干净,我补几个真正影响选型的点。

AIO 在 Linux 上不是内核真异步。 帖子表格把 AIO 标为「异步」在语言层面没错,但 JDK 的 AsynchronousChannelGroup 在 Linux 上是拿 epoll + 线程池模拟出来的,只有 Windows 的 IOCP 才是内核级真异步。所以在 Linux 部署的服务上,AIO 相对 NIO 拿不到性能优势,反而多一层线程池开销——Netty 放弃 AIO transport 就是这个原因。这条比模型定义更该在选型时被记住。

NIO 的「最小可用」和「生产可用」差着一段。 两个经典坑:一是 epoll 空轮询 bug,select() 返回 0 却没有任何就绪事件,循环空转把 CPU 打满,Netty 的解法是空轮询计数超阈值就重建 selector;二是 selectedKeys() 处理完必须 iterator.remove() 或循环后 clear(),漏了会事件重复触发甚至死循环。

选型我的判断: 连接数几百以内、内部服务、客户端 → BIO;万级长连接、网关、IM/push → Netty,别自己手写 Reactor;JDK 21+ 的 IO 密集型业务服务 → 虚拟线程 + BIO 直白写法,扩展性接近 NIO 但心智负担低太多,这一条正在改写原来「高并发必须 NIO」的结论。AIO 除非跑 Windows 或你有实测数据,否则直接跳过。

最后一个坑:半包/粘包不是 IO 模型能解决的,它属于编解码层(LengthFieldBasedFrameDecoder 这类),换成 NIO 一样会有,别在选型阶段把这两件事混在一起讨论。