对 Flask 应用做采样分析
在 Python3.7 环境下,Uber 开源的 PyFlame 无法使用,而在容器环境中,py-spy 又有诡异的问题。考量各种「采样」工具后,发现只有内置的 cProfile 才是稳定、可靠的。
但是对于复杂的 Flask App,大量使用 cProfile 执行采样非常不方便。本文将给出一个在
Python3.7 的容器环境下经测试可以正常工作的例子。原理是在 app
初始化后,添加
werkzeug ProfilerMiddleware(也许可以翻译成采样中间件)。
我们首先编写一个简单的 Flask App:
"""Profile uwsgi."""
from flask import Flask
from werkzeug.contrib.profiler import ProfilerMiddleware
import json
app = Flask('testapp')
@app.route('/')
def index():
return json.dumps({'status': 'ok'})
app.config['PROFILE'] = True
app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions = [30], profile_dir='/Users/ringsaturn/Downloads')
app.debug = True
app.run(host='0.0.0.0', port=8080, use_reloader=False)
然后运行这个 App,并访问 localhost:8080
# run server
python3 demo.py
# request
curl "http://localhost:8080"
服务端会对每一个请求,生成一个 prof
文件,并保存到指定的文件夹中。
为了可视化分析文件,需要使用 snakeviz
这个库。命令行中输入:
snakeviz GET.root.000000ms.1566789598.prof
随后会自动在浏览器中打开一个网页,样子如下:
一些注意事项:
- 不同项目,
app
的初始化位置不一样,app
很可能在初始化的过程中被封装了一层又一层,务必在最开始的时候做这个操作 ProfilerMiddleware
本质上调用的是 Python 内置的cProfile
工具,所以需要在和执行采样时的 Python 版本一致的情况下,执行snakeviz
命令。所以如果在做跨版本之间的比较,会用到虚拟环境或者 pyenv 这样的工具- 保存的目录必须事先存在,否则程序会报错
参考资料:
Read other posts