偶然在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
#!/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)
gunicorn -k gevent -b 0.0.0.0:8888 1:app
结果为Requests per second: 242.21 [#/sec] (mean)
没啥提升
#!/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)
没有提升
gunicorn -k gevent -b 0.0.0.0:8888 2:app
结果为Requests per second: 306.66 [#/sec] (mean)
有提升,但是也很有限。。。。
#!/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试一把。
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