42---IO模型

Posted kathrine

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了42---IO模型相关的知识,希望对你有一定的参考价值。

参考博客:https://www.cnblogs.com/linhaifeng/articles/7454717.html

一 IO模型

1.1 网络IO模型有很多,它们都是为了解决一个问题:减少IO等待时间,提高计算机效率

  • 应用程序遇到IO操作,会阻塞在原地等待,这样降低了计算机的执行效率。
  • 为了解决这个问题,先后出现了多种IO模型。
# 阻塞IO		blocking IO           
# 非阻塞IO		nonblocking IO      
# 多路复用IO	IO multiplexing      
# 信号驱动IO	signal driven IO     
# 异步IO		asynchronous IO    
由signal driven IO(信号驱动IO)在实际中并不常用,所以主要介绍其余四种IO Model。

1.2 IO发生时涉及到的两个对象

  • 一个是调用这个IO的任务对象(线程或进程)
  • 一个是系统内核(可以简单理解为操作系统)
  • IO模型的不同,主要体现在如何处理这以下两个阻塞阶段上
# IO操作时,两个对象之间存在两个行为阶段(两个阻塞阶段):
- 等待数据 wait data (Waiting for the data to be ready)
- 拷贝数据 copy data (Copying the data from the kernel to the process)

1.3 产生IO的行为

1、被动等待接受:read、readv、recv、recvfrom、recvmsg、accept
2、主动发送数据:write、writev、send、sendto、sendmsg、connect

# 网络IO主要表现在 accept、recv、recvfrom
# 被动等待数据的时间一般很长,这就是IO操作遇到阻塞的主要原因。
# 不论是收数据还是发送数据,都是直接跟自己的操作系统打交道,问自己的OS要数据或将数据交给OS发出去。
# 因此被动等数据的时间很长,主动发数据就很容易,因此可以不考虑send这种网络IO(忽略不计)。

二 网络IO模型

2.1 阻塞IO

默认所有IO都是阻塞IO。

  • 阻塞IO时:完完全全经历了wait datacopy data两个阻塞阶段,等待时间最长。
  • 解决办法:开多线程或多进程,同时处理多个客户端的请求,再设置半连接池和进程池(线程池)。
  • 缺点:系统硬件资源有限,不可能无限制的开多进程或多线程。
  • 适用:适用在小规模的并发服务请求。
    技术图片

2.2 非阻塞IO

可以将socket设置为非阻塞模式,此时acceptrecv就不会再原地等待了。

server.setblocking(False)	# 默认是True, 为阻塞IO
  • 非阻塞IO时,在wait data 阶段,应用程序可以干点别的事情,不会傻傻的原地等待,只是时不时地询问一下数据是否来到(轮询);数据到了后再经历 copy data 阻塞阶段获取数据。此时,只经历了copy data阻塞阶段
  • 解决办法:通过轮询的方式避免wait copy阶段的阻塞时间。
  • 缺点:<1> 轮询(长时间处于死循环状态)严重消耗硬件资源。<2> 轮询造成响应时间延长了。
  • 不推荐使用。

技术图片

2.3 多路复用IO

多路复用IO,是将轮询的任务单独拎出来,交给一个‘中介‘监管。应用程序只要向这个‘中介‘询问一次,‘中介‘就帮你等待,等数据到了再通知你过来取数据。相当于你向中介找房子,中介帮你等房源;等房源到了之后再通知你去看房。

  • 监管机制:监管机制(即‘中介‘)是操作系统内部的机制,可以调用select模块实现。
import select
r_list = [server]	# 将待监管的对象放在一起,交给select帮我们监管起来,后面的conn对象再放进去
readable_list, *_ = select.select(read_list, [], [])
  • 解决方法:监管机制,app无需经历wait data阻塞阶段,也不一直占用CPU资源(‘中介‘帮忙等数据)。
  • 优点:单线程(或进程)实现并发,降低IO等待时间。只经历copy data阻塞阶段
  • 缺点:
    • <1> 当并发规模过大时,造成响应延迟(遍历可读列表需要耗时增加);
    • <2> 监管对象极少时不如阻塞IO的多线程并发。
  • 适用:中等规模并发服务请求
  • 强调:应用程序不经历wait data 阻塞阶段,但整个进程或线程是被select阻塞的。
    技术图片
# 监管机制其实有很多
select机制  windows linux都有
poll机制    只在linux有   poll和select都可以监管多个对象 但是poll监管的数量更多

上述select和poll机制其实都不是很完美 当监管的对象特别多的时候,可能会出现 极其大的延时响应
epoll机制   只在linux有
	它给每一个监管对象都绑定一个回调机制
	一旦有响应 回调机制立刻发起提醒

针对不同的操作系统还需要考虑不同检测机制 书写代码太多繁琐
有一个人能够根据你跑的平台的不同自动帮你选择对应的监管机制

# selectors模块

2.4 异步IO

异步IO通过异步提交任务 + 回调机制的方式降低阻塞等待时间。

  • 原理:任务异步替提交后,不做任何等待,直接处理其他任务。相当于,我向中介找房子,中介接到任务后开始等待房源;等房源到了之后他自己主动先去看房,看房结束后,主动告诉我说好了可以去住了。
  • 操作系统收到数据后,主动将数据拷贝给app内存,然后通知app说数据好了,app不经历 copy data阻塞阶段。
  • 异步IO,应用程序不经历 wait datacopy data 两个阻塞阶段。
  • 优点:异步IO模型是所有模型中效率最高的,也是使用最广泛的
    技术图片
# 相关的模块和框架
- 模块:asyncio模块
- 异步框架:sanic tronado twisted

三 总结

技术图片

  • 阻塞IO, 经历两个阻塞阶段,可以用多线程(进程)实现小规模并发
  • 非阻塞IO,经历一个阻塞阶段,死循环严重消耗CPU资源,不推荐
  • 多路复用IO,经历两个阻塞阶段,通过监管机制,实现单线程内中等规模并发
  • 异步IO,不经历阻塞阶段,异步加回调机制,实现大规模高并发

以上是关于42---IO模型的主要内容,如果未能解决你的问题,请参考以下文章

42IO模型发展史

AJAX相关JS代码片段和部分浏览器模型

使用片段时 Intellij 无法正确识别 Thymeleaf 模型变量

php 一个自定义的try..catch包装器代码片段,用于执行模型函数,使其成为一个单行函数调用

如何防止在背面片段导航上再次设置视图模型

Cg入门19:Fragment shader - 片段级模型动态变色