网站首页 > 精选教程 正文
异步io的优势
传统web应用的一大缺点是,遇到io只能阻塞,等待处理完后再返回,在此期间,无法处理其他的请求。严重降低了系统的并发能力。而异步io则应用而生,本文将从协程、asyncio、aiohttp这三个方面介绍异步io的使用。
协程
协程和线程的区别
协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态。协程实际上是在一个线程中,只不过每个协程对CPU进行顺序分时使用。任务执行顺序用户可控。
线程,多线程共享进程中的资源,通过全局GIL锁来平均分配CPU,在不同线程中不断切换执行任务,任务执行顺序用户不能控制。
asyncio
asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。同时从Python 3.5开始引入了新的语法async和await,让协程的代码更简洁易读。基本用法如下:
import asyncio async def hello(): print("Hello world!") r = await asyncio.sleep(1) print("Hello again!") # 获取EventLoop: loop = asyncio.get_event_loop() # 执行coroutine loop.run_until_complete(hello()) loop.close()
使用步骤:
1.利用async关键字定义协程,利用await做异步io切换
2.获取eventloop
3.执行协程,等待所有协程执行完毕
线程和协程执行效率PK
这里我们测试1000个协程和线程执行时间耗时(模拟io时间为1s),代码如下:
from threading import Thread import time import asyncio async def hello(): r = await asyncio.sleep(1) pre_time = time.time() loop = asyncio.get_event_loop() tasks = [hello() for x in range(1000)] loop.run_until_complete(asyncio.wait(tasks)) loop.close() print('1000个协程耗时:', time.time() - pre_time, 's') def hello(): time.sleep(1) pre_time = time.time() threads = [Thread(target=hello) for x in range(1000)] for x in threads: x.start() for x in threads: x.join() print('1000个线程耗时', time.time() - pre_time, 's')
打印结果如下:
1000个协程耗时: 1.0314579010009766 s 1000个线程耗时 1.1242129802703857 s
显然,协程效率大于线程,若继续增大任务数目到10000呢?
打印显示:
10000个协程耗时: 1.2555210590362549 s _start_new_thread(self._bootstrap, ()) RuntimeError: can't start new thread
可以看出,多个协程切换时间依旧很小,而线程由于数目太多已经挂了,在这种io高并发场景中,协程完胜。
aiohttp
和asyncio的区别是:
asyncio实现了TCP、UDP、SSL等协议,aiohttp则是基于asyncio实现的HTTP框架。
在python中其他知名的异步io框架还有:
Tornado:异步非阻塞IO的Python Web框架,最新版本的异步协程是基于Python内置的asyncio来实现(老版本用装饰器实现异步)
Pulsar:Python的事件驱动并发框架
Diesel:基于Greenlet的事件I/O框架
安装:
pip install aiohttp
基本使用如下:
import asyncio from aiohttp import web async def index(request): await asyncio.sleep(0.5) return web.Response(body=b'<h1>Index</h1>') async def hello(request): await asyncio.sleep(0.5) text = '<h1>hello, %s!</h1>' % request.match_info['name'] return web.Response(body=text.encode('utf-8')) async def init(loop): app = web.Application(loop=loop) app.router.add_route('GET', '/', index) app.router.add_route('GET', '/hello/{name}', hello) srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000) print('Server started at http://127.0.0.1:8000...') return srv loop = asyncio.get_event_loop() loop.run_until_complete(init(loop)) loop.run_forever()
官方建议部署方式为:
nginx+supervisor,此种部署方式性能最佳
具体使用可以参考官方文档:
https://github.com/aio-libs/aiohttp
待研究问题
- flask项目改造为aiohttp能否只改造路由和异步request部分?
- 使用aiohttp的知名项目有哪些?还是选择tarnado比较稳妥?
猜你喜欢
- 2024-10-24 阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO 一文搞定
- 2024-10-24 搞定Nginx高并发原理:多进程单线程和多路IO复用模型
- 2024-10-24 JAVA分布式构架师 java 分布式框架有哪些
- 2024-10-24 NIO、BIO、AIO 与 PHP 实现 php or
- 2024-10-24 tarsweb平台搭建 tars web
- 2024-10-24 Java IO体系-彻底理解BIO、NIO、AIO
- 2024-10-24 Linux原生异步IO原理与实现(Native AIO)
- 2024-10-24 架构解密从分布式到微服务:深入理解网络,AIO
- 2024-10-24 nginx+consul做动态负载均衡(docker)
- 2024-10-24 linux下aio异步读写详解与实例《完整版》
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)