python的异步web框架 有:
- tornado
- aiohttp
- sanic
tornado: 支持同步异步,还支持长链接
aiohttp:是基于asyncio实现的HTTP框架
sanic: 是基于python3.5之上的一个web框架
官网上说sanic每秒中能处理的请求比同步更多,但是我之前一直是模糊的,觉得异步就应该比同步快。直到今天写例子做对比才发现远不是这样的。
对比测试
为了做对比,我使用flask写了个同步的请求,并设置了延迟5s
flask 测试
from flask import Flask
app = Flask(__name__)
import time
@app.route('/')
def hello_world():
print('start time: {0}'.format(datetime.now()))
time.sleep(5)
print('end time: {0}'.format(datetime.now()))
return 'Hello World!'
if __name__ == '__main__':
app.run()
浏览测试
在浏览器两个窗口发起请求,然后得到如下输入:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
start time: 2018-08-20 17:40:09.461917
127.0.0.1 - - [20/Aug/2018 17:40:14] "GET / HTTP/1.1" 200 -
end time: 2018-08-20 17:40:14.466055
start time: 2018-08-20 17:40:14.468269
end time: 2018-08-20 17:40:19.471463
127.0.0.1 - - [20/Aug/2018 17:40:19] "GET / HTTP/1.1" 200 -
注意,这里是一个请求处理完了,下个请求才能得到响应。两个请求总用时10s钟
jmeter 测试
然后将延迟修改为0.5,使用jmeter测试,测试参数:线程数:5 , 循环次数: 2000
测试机8核
结果数据跑到2700多条然后卡住了,我主动结束掉了,从开始到结束吞吐量都在 2/s
sanic 测试
使用sanic 来进行测试,测试代码
from sanic import Sanic
from sanic.response import json
import settings
import asyncio
app = Sanic()
@app.route('/')
async def test(request):
print('[{0}] start time: {1}'.format(request.transport, datetime.now()))
await asyncio.sleep(5)
print('[{0}] end time: {1}'.format(request.transport, datetime.now()))
return json({'hello': 'world'})
if __name__ == '__main__':
app.run(host=settings.HOST, port=settings.PORT)
浏览测试
在浏览器两个窗口发起请求,然后得到如下输入:
[2018-08-20 15:34:20 +0800] [48684] [INFO] Goin' Fast @ http://0.0.0.0:8000
[2018-08-20 15:34:20 +0800] [48684] [INFO] Starting worker [48684]
[<TCPTransport closed=False reading=True 0x101bbdf38>] start time: 2018-08-20 17:43:10.678247
[<TCPTransport closed=False reading=True 0x101bbe1f8>] start time: 2018-08-20 17:43:12.067509
[<TCPTransport closed=False reading=True 0x101bbdf38>] end time: 2018-08-20 17:43:15.687308
[2018-08-20 17:43:15 +0800] - (sanic.access)[INFO][1:2]: GET http://127.0.0.1:8000/ 200 17
[<TCPTransport closed=False reading=True 0x101bbe1f8>] end time: 2018-08-20 17:43:17.067715
[2018-08-20 17:43:17 +0800] - (sanic.access)[INFO][1:2]: GET http://127.0.0.1:8000/ 200 17
这里两个请求,请求先后都被接受,然后再进行处理,两个总用时7秒,少于10秒。比起同步代码,是有提升的
jmeter 测试
然后将延迟修改为0.5,使用jmter 测试参数一至,结果数据跑到2000多条的时候卡住了,怎么也不跑...(在mac上的jmeter这么不稳定?我以前都没遇到卡住的情况)
其中吞吐量随着请求数增多一直在上涨,在卡住的时候达到 9.9/s ,详细见下图
总结
使用sanic异步是让程序在一段时间范围内能接受更多的请求,而不至于阻塞在上一个请求中。 可以这样说,是多个请求时,可以提升访问量,而对于单个具体的请求,处理时间本身并不会缩短。这里画个图来总结下: