我正在 Heroku 上使用带有 eventlet 工作人员的 Gunicorn 运行 Flask 应用程序。我的应用程序上的特定路由经常接收 POST 数据 (x-www-form-urlencoded),其中包含一些相当大的字段 - 最多大约 500KB。
这在本地运行时效果很好,但在 Heroku 上,对该路由的请求需要 5 到 30 秒才能完成——而且几乎 100% 的时间都花在第一次访问 request.form 上:
t = time.time()
action = str(request.form['action'])
dt = time.time() - t # Often 10 seconds or more!
Newrelic 慢请求跟踪也证实了这一点。这里或那里有几毫秒的数据库操作,然后 Python 代码中的大量时间显然花在等待某些 I/O 上,因为报告的 CPU 时间通常小于一毫秒。
我完全无法使用我在生产中使用的相同的 Gunicorn/eventlet 设置在本地环境中重现这一点。即使内置的调试 WSGI 服务器对这些请求的处理速度也快如闪电。
有人知道可能出了什么问题吗?这是 Flask 的问题,还是我需要联系 Heroku 支持人员解决的问题?
我想我完全明白发生了什么事。 TL;DR 实际上,服务器端一点也不慢,我只是被 Newrelic 报告的响应时间误导了!
我尝试在 dotCloud 的沙箱上运行与 @AllanAnderson 建议的相同的代码。我首先创建了一个简化的测试用例:一个简单的 HTML 表单,其中包含一些预加载了大约 900KB 数据的隐藏字段,以及一个视图函数,该函数除了从 request.form 字典中读取数据并使用以下命令测量每次访问所用的时间之外,什么也不做:时间.时间()。
在 Heroku 上,结果如下所示:
5.87100 seconds: read field "p1": 786432 bytes
0.00019 seconds: read field "p2": 131072 bytes
0.00003 seconds: read field "p3": 12288 bytes
0.00001 seconds: read field "p4": 1024 bytes
在 dotCloud 上:
0.00096 seconds: read field "p1": 786432 bytes
0.00019 seconds: read field "p2": 131072 bytes
0.00003 seconds: read field "p3": 12288 bytes
0.00001 seconds: read field "p4": 1024 bytes
然而,这两个测试在我的浏览器中似乎花费了相同的时间......现在您可能已经猜到了这个“问题”的真正答案。 :-)
事实证明,Heroku 上的 Gunicorn 在收到标头后立即执行视图函数,并且对 request.form 的第一次访问被阻止,直到收到请求的其余部分。因此 Newrelic 看到了所有这些慢得离谱的响应时间,这实际上只是通过糟糕的网络连接上传 POST 数据的结果。 dotCloud 的设置显然只是等待整个请求被接收。
这使得 Newrelic 的指标不太有用,但这实际上并不是最终用户体验的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)