python 并发编程 阻塞IO模型原理解析


Posted in Python onAugust 20, 2019

阻塞IO(blocking IO)

在linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概是这样:

当用户进程调用了recvfrom这个系统调用,kernel内核就开始了IO的第一个阶段:准备数据。对于network io( 网络io )来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包),这个时候kernel( 内核 )就要等待足够的数据到来。

等着对方把数据放到自己操作系统内存

而在用户进程这边,整个进程会被阻塞。当kernel一直等到数据准备好了,它就会将数据从kernel操作系统缓存中拷贝到用户应用程序内存,

然后kernel返回结果,用户进程才解除block的状态,重新运行起来。

这就是阻塞IO

所以,blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了

网络编程都是从listen\(\)、send\(\)、recv\(\) 等接口开始的,
使用这些接口可以很方便的构建服务器/客户机的模型。然而大部分的socket接口都是阻塞型的。如下图

ps:

所谓阻塞型接口是指系统调用(一般是IO接口)不返回调用结果并让当前线程一直阻塞
只有当该系统调用获得结果或者超时出错时才返回。

服务端:

from socket import *
server = socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8000))
server.listen(5)
while True:
  print("starting...")
  conn,addr = server.accept()
  print(addr)
  while True:
    try:
      data = conn.recv(1024)
      if not data:break
      conn.send(data.upper())
    except ConnectionResetError:
      break
server.close()

客户端

from socket import *
client = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8000))
while True:
  msg = input(">>>:").strip()
  if not msg:continue
  client.send(msg.encode("utf-8"))
  data = client.recv(1024)
  print(data.decode("utf-8"))
client.close()

python 并发编程 阻塞IO模型原理解析

实际上,除非特别指定,几乎所有的IO接口 ( 包括socket接口 ) 都是阻塞型的。这给网络编程带来了一个很大的问题,如在调用recv(1024)的同时,线程将被阻塞,在此期间,线程将无法执行任何运算或响应任何的网络请求。

一个简单的解决方案:

在服务器端使用多线程(或多进程)。多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),
这样任何一个连接的阻塞都不会影响其他的连接。

该方案的问题是 :

开启多进程或都线程的方式,在遇到要同时响应成百上千路的连接请求,则无论多线程还是多进程都会严重占据系统资源,
降低系统对外界响应效率,而且线程与进程本身也更容易进入假死状态。
随着客户端数量增多,无限制的开线程,开销非常大
不能解决阻塞IO问题 ,解决思路:起多线程

改进方案:

使用“线程池”或“连接池”。“线程池”旨在减少创建和销毁线程的频率,
其维持一定合理数量的线程,并让空闲的线程重新承担新的执行任务。“连接池”维持连接的缓存池,尽量重用已有的连接、
减少创建和关闭连接的频率。这两种技术都可以很好的降低系统开销,都被广泛应用很多大型系统,如websphere、tomcat和各种数据库等。

改进后方案其实也存在着问题:

“线程池”和“连接池”技术也只是在一定程度上缓解了频繁调用IO接口带来的资源占用。而且,所谓“池”始终是有限,
当请求大大超过上限时,“池”构成的系统对外界的响应并不比没有池的时候效果好多少。所以使用“池”必须考虑其面临的响应规模,

并根据响应规模调整“池”的大小。

线程池应该随着规模数调大,但是调大线程池,要在机器可承受范围之内。不能把线程池无限调大,这样相当于无限开线程一样,

多线程还是要用在规模比较小的情况

对应上例中的所面临的可能同时出现的上千甚至上万次的客户端请求,“线程池”或“连接池”或许可以缓解部分压力,但是不能解决所有问题。总之,多线程模型可以方便高效的解决小规模的服务请求,但面对大规模的服务请求,多线程模型也会遇到瓶颈,可以用非阻塞接口来尝试解决这个问题。

总结:

始综没有解决单线程遇到IO问题,单线程遇到IO,就阻塞,用的是阻塞IO模型。

阻塞IO模型就是遇到IO阻塞不处理,就在原地等着。

应该:

监测单线程IO,遇到IO了,这个线程不要阻塞。直接切换到另外一个线程运行,这样单线程效率就非常高了。

要解决的问题是:

单线程IO问题

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python多线程实例教程
Sep 06 Python
Windows8下安装Python的BeautifulSoup
Jan 22 Python
python生成随机mac地址的方法
Mar 16 Python
快速了解python leveldb
Jan 18 Python
python自动化报告的输出用例详解
May 30 Python
python生成九宫格图片
Nov 19 Python
Centos部署django服务nginx+uwsgi的方法
Jan 02 Python
Python基于pandas爬取网页表格数据
May 11 Python
Python中的特殊方法以及应用详解
Sep 20 Python
Django2.1.7 查询数据返回json格式的实现
Dec 29 Python
Django视图类型总结
Feb 17 Python
Python中可变和不可变对象的深入讲解
Aug 02 Python
PyTorch中常用的激活函数的方法示例
Aug 20 #Python
Pytorch抽取网络层的Feature Map(Vgg)实例
Aug 20 #Python
python批量解压zip文件的方法
Aug 20 #Python
pytorch获取vgg16-feature层输出的例子
Aug 20 #Python
python 并发编程 非阻塞IO模型原理解析
Aug 20 #Python
Python实现某论坛自动签到功能
Aug 20 #Python
python函数的作用域及关键字详解
Aug 20 #Python
You might like
PHP面向对象学习笔记之一 基础概念
2012/10/06 PHP
深入理解:XML与对象的序列化与反序列化
2013/06/08 PHP
PHP聚合式迭代器接口IteratorAggregate用法分析
2017/12/28 PHP
ThinkPHP5与单元测试PHPUnit使用详解
2020/02/23 PHP
jQuery 使用个人心得
2009/02/26 Javascript
jBox 2.3基于jquery的最新多功能对话框插件 常见使用问题解答
2011/11/10 Javascript
jQuery拖拽 & 弹出层 介绍与示例
2013/12/27 Javascript
javascript类型转换使用方法
2014/02/08 Javascript
js动态移动滚动条至底部示例代码
2014/04/24 Javascript
PHP实现的各种中文编码转换类分享
2015/01/23 Javascript
JQuery手速测试小游戏实现思路详解
2016/09/20 Javascript
Angular2 路由问题修复详解
2017/03/01 Javascript
利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
2017/11/20 Javascript
基于vue开发的在线付费课程应用过程
2018/01/25 Javascript
js 解析 JSON 数据简单示例
2020/04/21 Javascript
vue中选中多个选项并且改变选中的样式的实例代码
2020/09/16 Javascript
python实现简单的socket server实例
2015/04/29 Python
Python中psutil的介绍与用法
2019/05/02 Python
Python数据类型之String字符串实例详解
2019/05/08 Python
基于Python实现剪切板实时监控方法解析
2019/09/11 Python
python3.7 openpyxl 删除指定一列或者一行的代码
2019/10/08 Python
Pytorch生成随机数Tensor的方法汇总
2020/09/09 Python
Python绘图实现台风路径可视化代码实例
2020/10/23 Python
Python Pandas数据分析工具用法实例
2020/11/05 Python
世界上最大的字体市场:MyFonts
2020/01/10 全球购物
德国50岁以上交友网站:Lebensfreunde
2020/03/18 全球购物
汽车专业毕业生推荐信
2013/11/12 职场文书
学术会议欢迎词
2014/01/09 职场文书
旅游个人求职信范文
2014/01/30 职场文书
先进工作者获奖感言
2014/02/08 职场文书
机工车间主任岗位职责
2014/03/05 职场文书
土木工程求职信
2014/05/29 职场文书
校园绿化美化方案
2014/06/08 职场文书
教师国庆节演讲稿范文2014
2014/09/21 职场文书
2014班子成员自我剖析材料思想汇报
2014/10/01 职场文书
JS前端轻量fabric.js系列物体基类
2022/08/05 Javascript