IO 基础

基础

1 Linux IO模型

Linux的IO操作一般分为两个动作:

  1. 等待数据达到
  2. 将数据从内核copy到用户空间

1.1 阻塞IO模型

在进程中调用recvFrom,其系统调用直到数据包到达并且被复制到应用进程缓存区中或发生错误时才返回,在此期间一直处于阻塞状态。
数据到达:同步阻塞
数据复制:同步阻塞

1.2 非阻塞IO模型

recvFrom从应用到内核的时候,如果缓冲区没有数据的话,就直接返回错误,一般情况下常使用轮询方式进行数据到达的检查。

数据达到:轮询
数据复制:同步阻塞

1.3 IO复用模型

Linux提供select/poll,进程通过将一个或多个fd传递给select/poll系统调用,阻塞在select方法上,这样select/poll可以帮我们检测多个fd是否处于就绪状态,当有数据达到时,调用recvfrom将数据从内核copy到用户进行缓冲区。
select/poll是顺序扫描fd是否就绪,支持的fd数量有限。
epoll使用事件驱动方式替代顺序扫描,性能更好。

数据到达:select阻塞
数据复制:同步阻塞

1.3.1 IO多路复用

IO多路复用通过把多个IO的阻塞复用到同一个select阻塞上,从而使系统在单线程的情况下可以同时处理多个客户端请求。

1.3.2 select VS epoll
1.3.2.1 支持的socket文件句柄数量

select:1024,需要修改内核并编译
epoll:没有限制,1G内存可以容纳10W左右

1.3.2.2 socket文件句柄多时,性能下降

select:顺序遍历
epool:事件回调

在活跃socket数量多时,select有一定优势,活跃socket少时,epoll有绝对优势

1.3.2.3 信息交换MMAP

epoll通过内核和用户空间mmap同一块内存实现。

1.4 信号驱动IO模型

首先开启嵌套字接口信号驱动io功能,通过系统调用sigaction执行一个信号处理函数,当数据准备就绪时,为该进程生产一个SIGIO信号,通过信号回调通知应用程序调用recvfrom函数获取数据。

数据达到:信号驱动
数据复制:同步阻塞

1.5 异步IO模型

告知内核启动某个操作,并让内核在整个操作完成后通知我们。
这个模型与信号驱动模型的主要区别是:
信号驱动模型通过我们何时可以开始io操作
异步io模型通知我们io操作何时已经完成

2 Java IO

2.1 BIO

基于流的阻塞IO
通常有一个独立的线程负责监听客户端的连接,接收到客户端请求后,为每一个客户端创建一个线程进行链路处理。

2.1.1 ServerSocket
2.1.2 Socket
2.1.3 伪异步IO

使用线程池处理每个链路的请求。

2.2 NIO

非阻塞IO,可以支持IO多路复用。
提供快速面向块的IO。

2.2.1 Buffer

是一个容器对象,其中包含要写入或要读取的数据。
缓存实际是一个数组,一般为字节数组。

2.2.2 Channel

channel是一个通道,可以通过它读取或写入数据。
流只是一个方向上的移动。
通道可以用于读、写或同时用于读写。

SelectableChannel

网络读写

ServerSocketChannel

SocketChannel

FileChannel

文件操作

2.2.3 selector

多路复用器提供选择已经就绪的任务的能力。
Selector会不停的轮询注册在其上的Channel,如果某个Channel上有新的IO连接进来、读或写操作,这个Channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey获取就绪的Channel集合,然后进行IO操作。

2.2.4 字符编解码
2.2.5 正则

2.3 NIO2.0

提供文件操作、AIO

2.3.1 文件属性操作
2.3.2 AIO

异步+回调方式,实现真正的异步非阻塞IO。
JDK底层通过线程池ThreadPoolExcutor来执行回调通知。
异步SocketChannl是被动执行对象,由底层JDK负责回调并驱动读写操作。

2.3.2.1 AynchronousServerSocketChannel
2.3.2.2 AsynchronousSocketChannel
2.3.3 配置和多播

3 粘包/拆包

TCP是一个基于流的协议,所谓流就是没有界限的一串数字。
一个完整的业务包,可以被分割为多个TCP包进行发送,称为拆包;也可以将多个业务包通过一个TCP包进行发送,称为粘包。

3.1常用解决方案

3.1.1 定长消息

选择定长消息,不足则空位补零。

3.1.2 固定分隔符

在业务包后添加固定分隔符。
FTP协议,末尾添加回车换行符。

3.1.3 消息头+消息体

在消息头中包含消息的Meta信息(消息的总长度)

3.1.4 其他应用协议

4 Reactor线程模型

线程模型的好坏决定了系统的吞吐量、并发量和安全性等架构质量

4.1 单线程模型

所有的有IO操作都在同一个NIO线程上面完成。

4.2 多线程模型

由一组NIO线程来处理IO操作

4.3 主从多线程模型

由两个acceptor组成,一个负责连接建立、一个负责IO读写

wenxinzizhu wechat
扫一扫,添加我的微信,一起交流共同成长(备注为技术学习)