IO的演进之路

学习目的

打造网络知识的体系

学习方法

  • 网络的初步了解 (DOING)
  • 极客时间—— 趣谈网络协议
  • netty api的熟悉和了解
  • netty源码的学习
  • netty demo (自研IM)

IO演进之路

下面讲述IO的演进之路,从简到繁,实现的复杂度越高,优化程度越明显。

铺垫

在unix系统中,一切皆文件(fd)

1、BIO 阻塞性IO

最原始的IO方式,客户端每次调用都要消耗服务端一个线程,服务端会被阻塞。在进程空间去,会去调用系统提供的recefrom函数,系统会一直被阻塞。直到网络套接字Socket的数据到达或者发送错误,系统才会从阻塞状态中唤醒。也就是说,系统从收到recefrom函数 -> 返回网络套接字,程序都是一直被阻塞的。

其示意图如下

bio 线程模型.jpg

思考:
BIO的处理模型,设计非常简单,但是无法支撑高并发连接,如果面对成千上万的客户端连接,服务端的线程资源不足,很容易就会到达连接上限。

2、NIO 非阻塞性IO

系统在收到recefrom函数时候,不会阻塞,而是返回报错标志(EWOURLDBLOCK),系统可以去轮询检查这个报错标志的状态,一旦没有报错的标志,证明网络络套接字Socket的数据到达或者发送错误。

其示意图如下

NIO 线程模型.jpg

思考
这种非阻塞IO的好处很明显,服务端程序使用recefrom函数调用后,如果从系统内核拿到的是报错标志,服务端程序可以开启一个后台线程一直轮询这个标志,在此期间,服务端程序不用一直阻塞,可以用其他线程去处理剩余的程序,等后台线程轮询的结果为成功,再去处理Socket返回的数据或者错误。

但是缺点也很明显,应用程序要额外去处理连接,并且处理的大小有限,因为应用程序的线程资源是有限的。无法处理过多的请求。

3、信号驱动IO (重点解析)

应用程序通过, linux系统提供的select/poll 方法,将套接字传给linux系统,然后应用系统会阻塞在select/poll 上,等待linux接受到网络套接字socket后,这个时候应用程序会被linux系统唤醒,调用recefrom的方法, Linux程序这个时候会把数据从内核态copy到用户态,应用程序就能拿到对应的socket套接字进行业务的操作了。

Selector模型.png

到达这里就会引入面试的热点, select模型和epoll模型,其实这两个模型都是基于信号驱动IO的一种实现,通过信号驱动的方式来进行通知应用程序。

先说结论: epoll模型是select模型的升级版本,主要是用来解决select模型查询低效的问题,select模型要轮询所有的套接字socket,时间复杂度为o(n),在面对成千上万的socket连接,效率会显得过慢,因此select也有1024个套接字socket的限制。 而epoll突破这种1024的限制,支持成千上万的连接,效率尤为高效。

3.1 select模型

其示意图如下,可以直接从第六步开始即可,select调用的逻辑。

SELECT模型.jpg

可以看到select模型工作流程如下:

    1. 应用程序在等待socket的返回之时,进程会被进行阻塞,被系统进行挂起。
    1. 这时候远程的数据返回,socket数据准备就绪,会给进程去发一个通知信号,唤醒等待中的进程
    1. 进程马上去轮询,fd数组中,哪些socket已经准备好了
    1. 应用程序拿到需要的数据进行对应的程序处理。。。。

3.2 epoll模型

我们可以看到,因为select需要取轮询fd数组,在面对成千上万的连接,效率显得尤为低效,操作系统为了解决这种问题,提出了epoll的解决方案。

epoll是通过增加一个新的对象,eventpoll对象将socket存储在当中,具体的eventpoll数据结构是双向链表 + 红黑树。

当应用程序在等待socket返回的时候,系统会将socket保存到eventpoll对象中的等待队列上,这时候,应用程序也会被添加到 等待队列 上。

PS: 这里可以看到,所有的socket,应用程序的操作都在这个eventpoll对象上完成

这时候,第三方应用返回socket数据,会唤醒eventpoll对象中的某一个等待数据的 socket, 并且也会唤醒对应的进程, 将他们添加到eventpoll的就绪列表中。因为应用程序和准备好的socket都在就绪列表中,因此应用程序是清楚知道哪个socket是就绪好了的。 OK,这时候再对对应的socket进行数据操作。。。

4. AIO

AIO, 全异步回调,应用程序在等待socket返回的时候,无需阻塞进程,直接由操作系统将数据从内核态返回给用户态,应用程序只需要收回调即可。

image.png

猜你喜欢

转载自juejin.im/post/7048790892609552397