这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记
IO阶段
典型的一次IO的2个阶段是什么?
数据就绪和数据读写
数据就绪:根据系统IO操作的就绪状态
- 阻塞5
- 非阻塞
数据读写:根据应用程序和内核的交换方式
- 同步:程序主动搬数据到自己的缓冲区中
- 异步:程序告知内核将数据搬到哪儿,以及通知方式,然后程序可以去做别的事,由内核搬运数据
同步表示A向B请求调用一个网络IO接口时(或者调用某个业务逻辑API接口时),数据的读写都是由请求方A自己来完成的(不管是阻塞还是非阻塞)﹔异步表示A向B请求调用一个网络IO接口时(或者调用某个业务逻辑API接口时),向B传入请求的事件以及事件发生时通知的方式,A就可以处理其它逻辑了,当B监听到事件处理完成后,会用事先约定好的通知方式,通知A处理结果。
Linux上的五种IO模型
阻塞
非阻塞
IO复用
信号驱动
异步IO模型
HTTP协议
HTTP协议(超文本传输协议HyperText Transfer Protocol),它是基于TCP协议的应用层传输协议,简单来说就是客户端和服务端进行数据传输的一种规则。
HTTP 是一种无状态 (stateless) 协议, HTTP协议本身不会对发送过的请求和相应的通信状态进行持久化处理。这样做的目的是为了保持HTTP协议的简单性,从而能够快速处理大量的事务, 提高效率。
HTTP请求报文格式
HTTP相应报文格式
HTTP的五大特点
- 支持客户/服务器模式。
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有
GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。 - 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由
Content-Type加以标记。 - 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。早期这么做的原因是请求资源少,追求快。后来通过
Connection: Keep-Alive实现长连接 - 无状态:
HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
2种事件处理模式
服务器程序通常要处理三类事件:I/O事件、信号和定时事件。两种高效的事件处理模式:Reactor和Proactor。一般地,同步I/O模型常用于实现Reactor模式,异步I/O模型则用于实现Proactor模式。
1.Reactor模式
Reactor是一种这样的模式,它要求主线程(I/O处理单元)只负责监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作线程(逻辑单元)。除此之外,主线程不作任何其他实质性工作。读写数据,接收新的连接,以及处理客户请求均在工作线程完成。
使用同步I/O模型(以epoll_wait为例)实现的Reactor模式的工作流程是:
- 主线程往epoll内核事件表中注册socket读就绪事件;
- 主线程调用epoll_wait等待socket上有数据可读;
- 当socket上有数据可读时,epoll_wait通知主线程。主线程则将socket可读事件放入请求队列;
- 睡眠在请求队列上的某个工作线程被唤醒,它从socket读取数据,并处理客户请求,然后往epoll内核事件表中注册该socket上的写就绪事件;
- 主线程调用epoll_wait等待socket可写;
- 当socket可写时,epoll_wait通知主线程,主线程将socket可写事件放入请求队列;
- 睡眠在请求队列上的某个工作线程被唤醒,它往socket上写入服务器处理客户请求的结果。
2.Proactor模式
Proactor模式将所有I/O操作都交给主线程和内核来处理,工作线程仅负责业务逻辑。
使用异步I/O模型(以aio_read和aio_write为例)实现的Proactor模式工作流程是:
- 主线程调用aio_read函数想内核注册socket上读完成事件,并告诉内核用户读缓冲区的位置,以及读操作完成时如何通知应用程序;
- 主线程继续处理其他逻辑;
- 当socket上的数据被读入用户缓冲区后,内核将向应用程序发送一个信号,以通知应用程序数据已经可用;
- 应用程序预先定义好的处理函数选择一个工作线程来处理客户请求。工作线程处理完客户请求以后,调用aio_write函数想内核注册socket上的写完成事件,并告诉内核用户写缓冲区的位置,以及写操作完成时如何通知应用程序;
- 主线程继续处理其他逻辑;
- 当用户缓冲区的数据被写入socket之后,内核将向应用程序发送一个信号,以通知应用程序数据已经发送完毕;
- 应用程序预先定义好的信号处理函数选择一个工作线程来做善后处理,比如决定是否关闭socket.
3.两者的区别
Reactor模式适用于耗时短的处理场景,同时接受多个服务请求,并且一次同步的处理它们的事件驱动程序。
Proactor则适用于耗时长的处理场景,异步接受和同时处理多个服务器请求的事件驱动程序。