Python Async! 二十行代码的改变,让qps吞吐量高7倍!

响应变化,是敏捷的美德。

团队一直采用python-flask框架做web开发,最近业务扩大规模,需要能够承载峰值为10000的qps,团队准备用GO语言写API接口,在此之前,我使用python3.5的新语法async/await改写了API,对协程做了初步的探索。

代码都比较简单,我直接放在下面,让大家对新老API有个直观的了解。

FLASK框架的API(以下称老接口):

from flask import Flask, request, jsonify
from models import get_question_analysis

app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
    return 'hello world'

@app.route('/api', methods=['POST'])
def api():
    data = request.get_json()
    question = data['question']
    question_analysis = get_question_analysis(question)
    return jsonify(question_analysis)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=False)

使用ASYNC语法,aiohttp框架下的API(以下称新接口):

from aiohttp import web
from models import get_question_analysis

async def index(request):
    return web.Response(text='Hello World')

async def api(request):
    data = await request.json()
    question = data['question']
    question_analysis = await get_question_analysis(question)
    return web.json_response(question_analysis)

app = web.Application()
app.add_routes([web.get('/', index),
                web.post('/api', api)])

if __name__ == '__main__':
    web.run_app(app, host='0.0.0.0', port=5000)

针对两个接口,我用了两种方法做测试,过程如下:

方法一:用本机(macOS)ab(apache benchmark)直接做性能测试

测试方法:在命令行输入ab -c [concurrency] -n [total requests] T 'application/json' —p [filename] http://localhost:5000/api

通过更改"每秒并发数"和"服务进程数",得知:

  • 12个进程,500并发,老接口的理论qps值为550,而新接口的理论qps值为4023,提高了7倍
  • 1个进程,100并发,老接口的理论qps值为88,而新接口的理论值为522,提高了6倍


    Python Async! 二十行代码的改变,让qps吞吐量高7倍!_第1张图片
    ab数据对比

优点:

  • ab很简单,macOS与linux命令行原生自带,直接可用,数据清晰

缺点:

  1. 本机测试无法准确给出单个request的响应时间,实际业务中timeout的情况无法准确分析;
  2. qps值为理论值,实际业务中程序调度,机器负荷的花费无法考虑

方法二:用grafana.***.net做压力测试

测试方法:(蔽司的一个压测工具)模拟线上请求对API打压

数据分析:在打压API时,会返回每次请求的响应时间csv

为了满足业务50%请求的平均响应时间都在10ms以内的要求,我分别对新老接口(12个进程/台)进行了压力测试:

  • 新接口


    Python Async! 二十行代码的改变,让qps吞吐量高7倍!_第2张图片
    请求时间(new)
  • 老接口({qps: 400, avg: 25}, {qps: 300, avg: 14} {qps: 200, avg: 13})
    Python Async! 二十行代码的改变,让qps吞吐量高7倍!_第3张图片
    请求时间(old)

可以看到,在3500的并发下,新接口都能保持良好的性能,50%的请求都能在7ms内完成,并且响应时间的均值为8ms;另一方面,老接口的性能就难以保证,在400并发下,平均响应时长高达27ms。

到现在,我们应该知道python async的性能是非常优秀的,在我看来,接口的性能仍然有提升的空间,希望以后能够有更多的时间来探索、测试和分享。

你可能感兴趣的:(Python Async! 二十行代码的改变,让qps吞吐量高7倍!)