Java的IO模型、Netty原理详解
1.什么是IO
虽然作为Java开发程序员,很多都听过IO、NIO这些,但是很多人都没深入去了解这些内容。
- Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等
2.同步与异步、阻塞与非阻塞
- 同步:一个任务完成之前不能做其他操作,必须等待。
- 异步:一个任务完成之前,可以进行其他操作
- 阻塞:相对于CPU来说,挂起当前线程,不能做其他操作只能等待
- 非阻塞:CPU无需挂起当前线程,可以执行其他操作
3.三种IO模型
BIO(Blocking I/O)
同步并阻塞模式,调用方在发起IO操作时会被阻塞,直到操作完成才能继续执行,适用于连接数较少的场景。
例如:服务端通过ServerSocket监听端口,accept()阻塞等待客户端连接。
优缺点:
- 优点:实现简单
- 缺点:线程资源开销大,连接数多时,每个线程都要占用CPU资源,容易出现性能瓶颈
适用于低并发、短连接的场景,如传统的HTTP服务
NIO(Non-blocking I/O)
同步非阻塞模型,客户端发送的连接请求都会注册到Selector多路复用器上,服务器端通过Selector管理多个通道Channel,Selector会轮询这些连接,当轮询到连接上有IO活动就进行处理。
NIO基于 Channel 和 Buffer 进行操作,数据总是从通道读取到缓冲区或者从缓冲区写入到通道。Selector 用于监听多个通道上的事件(比如收到连接请求、数据达到等等),因此使用单个线程就可以监听多个客户端通道。
IO多路复用:一个线程可对应多个连接,不用为每个连接都创建一个线程
核心组件:
- Channel:双向通信通道(如SocketChannel),数据可流入流出
- Buffer:数据缓冲区,是双向的,可读可写
- Selector:一个Selector对应一个线程,一个Selector上可注册多个Channel,并轮询多个Channel的就绪事件
优缺点:
- 可以减少线程数量,降低线程切换的开销,适用于需要处理大量并发连接的场景
- 缺点:实现复杂度高
使用于高并发、长连接的场景,如即时通讯场景
AIO(Asynchronous I/O)
异步非阻塞模型,基于事件回调或Future机制
- 调用方发起IO请求后,无需等待操作完成,可继续执行其他任务。操作系统在IO操作完成后,通过回调或事件通知的方式告知调用方
- Java中
AsynchronousSocketChannel
是AIO的代表类,通过回调函数处理读写操作完成后的结果
优缺点:
- IO密集型的应用,AIO提供更高的并发和低延迟,因为调用方在等待IO时不会被阻塞
- 缺点:实现复杂
适用于高吞吐、低延迟的场景,如日志批量写入
4.什么是Netty
说起Java的IO模型,绕不开的就是Netty框架了,那什么是Netty,为什么Netty的性能这么高呢?
- Netty是由JBOSS提供的一个Java开源框架。提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器
- Netty的原理就是NIO,是基于NIO的完美封装
很多中间件的底层通信框架用的都是它,比如:RocketMQ、Dubbo、Elasticsearch
4.1 Netty的核心要点
核心特点:
- 高并发:通过多路复用Selector实现单线程管理大量连接,减少线程开销
- 传输快:零拷贝技术,减少内存拷贝次数
- 封装性:简化NIO的复杂API,提供链式处理(ChannelPipeline)和可扩展的