Sanic
- sanic使用基于libuv的uvloop事件循环替代python asnycio自带的事件循环替代,以此提高异步性能。
- Flask和Django是同步框架,Tornado、FastApi和Sanic均为异步框架,Sanic的性能最好。
- Sanic入门教程:Sanic:一款号称 Python 中性能最高的异步 web 框架,全方位介绍 Sanic
- Sanic支持通过workers设置并发的工作进程,开启多进程并发后,子进程会开启多个服务,主进程内部通过路由分发实现负载均衡。
uvloop
-
uvloop是Python原生事件循环的替代品,能提高了性能。
-
为什么提高了性能?:
- uvloop是基于Cython写的,执行效率更高。
- uvloop底层基于libuv,而libuv是高性能、跨平台的异步IO库,nodejs的事件循环也是基于libuv的。【libev介绍详见:网络io模型、同步异步及libuv】
-
缺点:uvloop不支持Windows。
-
即便不开发 Sanic 服务,也可以使用 uvloop 来替换 asyncio 内部的事件循环。
import asyncio
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
uvloop的性能测试
- 结论:纯uvloop的性能直逼Golang,但是Python的其他异步库可能成为性能瓶颈,如aiohttp的http解析。
- 如果追求性能,建议使用Golang。
uvloop官方测试结果
TCP协议
这是用简单的echo服务做的测试,不能代表所有生产环境的情况。
- 分别用1KiB数据包、10KiB、100KiB做了测试。
- 可以看到uvloop确实牛逼,性能直逼Go。
HTTP协议
- 【解释】:官方人员本来想用aiohttp这个Python中最常用的异步http服务库测试的。但是它的http解析器效率太低了,已然成为整个系统的瓶颈,所以他们手动实现了http-parser(起初是为Nginx设计的,所以效率非常高)的Python版本,称之为httptools。
- uvloop对aiohttp并没有性能提升!
第三方测试
- 参考web框架的性能排名榜:Web Framework Benchmarks
- 使用uvloop的Sanic性能并不如Gin。
对Asyncio局限的讨论
Python基于协程的异步是为了弥补GIL对多线程并发的限制。
如果追求性能,建议使用原生支持高并发和协程的语言,如:Golang、node.js等,代价就是切换技术栈,开发成本的增加。
同步和异步代码难以统一
- 同步和异步的语法 和 开发思路不同,导致代码维护成本翻倍。
- 同步代码可以利用多线程并发,但是协程不是线程安全的,而且多线程会导致协程效率变差,甚至不如多线程并发效率。
- 异步代码需要处处async/await,但是如果使用库不支持异步,仍然为io同步,也就没有意义。
大量库仍然是同步的
目前主要是很多库还是同步的。
只要有一处同步就会阻塞整个线程及其中的所有协程。
Python官方日志库logging
- 直到Python3.11仍然是同步的,如果业务代码中必然大量输出日志,日志会成为整个框架或脚本的性能瓶颈。
- 可选的异步库:
- aiologger:star非常少,可靠性未知。
- 注意:aiologger仅当登录到 stdout/stderr 时才完全异步。如果您登录磁盘上的文件,则您并不是完全异步的,而是将使用线程。
Python内置的Open操作文件
- 直到Python3.11仍然是同步的,
- 可选备用库:
- aiofiles:star较多可靠。
- 底层是基于线程池:aiofiles helps with this by introducing asynchronous versions of files that support delegating operations to a separate thread pool.
- aiofiles:star较多可靠。
aiohttp库
- uvloop的测试人员发现该库的http解析器性能很差,所有用Python把Nginx的http解析重新实现了一遍。
statsd库
- pystatsd:该库用于向statsD服务打点,常用于搭建监控系统,配合Grafana和Graphite使用。
- 可选的异步库:
- aiodogstatsd:star非常少,可靠性未知。
- udp-echo-server:使用异步框架,发送upd,自己完成封装。
参考资料
- Python 协程系列之EventLoop
- 你必须要会uvloop!让Python asyncio异步编程性能直逼Go协程性能