那年那日那朵花

".......(o´ω`o)......"

requests+flask性能测试

2017-08-31 12:30 linux python

引子

偶然在v2ex上看到这个帖子 ,是关于讨论在flask中大量使用requests调用外部接口而造成的性能影响。出于好奇,我也在本地做了下测试,并将其总结归纳一下。

开始测试

测试方案是先写个一个简单的接口供外部服务调用,然后外部调用通过requests、httplib2、requests共享sessions、gevent+requests等不同的方式来验证那种方法更快。

好那就开始了

先把本地服务器的内核参数调下

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

然后编写一个简单的接口服务

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from flask import Flask, request, render_template, session, flash, redirect,url_for, jsonify
import requests

app = Flask(__name__)

@app.route("/show")
def show():
    return jsonify({'state':"show"}), 200

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

所有测试使用ab进行,看其接口的吞吐量rps,ip和port皆为本地ip和port

ab -c 100 -n 5000 http://192.168.192.129:8888/req

方案一,直接使用requests.get

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from flask import Flask, request, render_template, session, flash, redirect,url_for, jsonify
import requests

app = Flask(__name__)

@app.route("/req")
def req():
    a = requests.get("http://127.0.0.1:18888/show")
    return jsonify({'state':"req"}), 200

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

使用gunicorn启动
gunicorn -b 0.0.0.0:8888 1:app

结果为Requests per second: 236.82 [#/sec] (mean)

方案二,给其打上gevent的monkey_patch

gunicorn -k gevent -b 0.0.0.0:8888 1:app

结果为Requests per second: 242.21 [#/sec] (mean)

没啥提升

方案三,使用requests并且共享session,同时调大pool_connections和pool_maxsize参数

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from flask import Flask, request, render_template, session, flash, redirect,url_for, jsonify
import requests

app = Flask(__name__)

s = requests.session()
myAdapter = requests.adapters.HTTPAdapter(pool_connections=1000,pool_maxsize=1000)
s.mount('http://', myAdapter)

@app.route("/req")
def req():
    a = s.get("http://127.0.0.1:18888/show")
    return jsonify({'state':"req"}), 200

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

gunicorn -b 0.0.0.0:8888 2:app

结果为Requests per second: 234.21 [#/sec] (mean)

没有提升

方案四,给其打上gevent的monkey_patch

gunicorn -k gevent -b 0.0.0.0:8888 2:app

结果为Requests per second: 306.66 [#/sec] (mean)

有提升,但是也很有限。。。。

方案五,使用httplib2作为接口请求的方式

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from flask import Flask, request, render_template, session, flash, redirect,url_for, jsonify
import httplib2

app = Flask(__name__)

@app.route("/req")
def req():
    h = httplib2.Http()
    resp, content = h.request("http://127.0.0.1:18888/show", "GET")
    return jsonify({'state':"req"}), 200

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

gunicorn -b 0.0.0.0:8888 3:app

结果为Requests per second: 344.04 [#/sec] (mean)

唔.....确实有提升。最后再使用gevent试一把。

方案六,给其打上gevent的monkey_patch

gunicorn -k gevent -b 0.0.0.0:8888 3:app

Requests per second: 417.14 [#/sec] (mean)

嗯。。。。。。有效有效

总结一下

在我纯粹使用requests.get方法请求外部的时候,对于加上gevent来说。确实没什么效果。而当我使用共享session的时候,一般而言也没啥效果。打上monkey_patch后,虽然有效但是提升并不是非常大,所以开头帖子里所说的gevent和requests库相性不合是有点道理的。但是,将requests改用httplib2并且打上monkey_patch后,效果提升还是比较大的。不过我这里gunicorn使用的是默认两个进程并没有充分使用多核机器的性能,所以测试结果只能算个参考,并非真正的峰值。而且对于开发代码来说,requests库虽然慢了点,但是比起httplib2来说确实好用、功能多,对于性能瓶颈来说可以尝试负载均衡后添加多节点来提高整体的性能指标。

Cloudhu 个人随笔|built by django|

沪ICP备16019452号-1