今天我试着写一个 web 服务,作为一个笑话http://dont-tread-on-memes.controversial.io。这是一个 Flask 应用程序,用于处理相当大的图像。Flask 应用程序本身运行良好,独立的 uWSGI 服务器也一样,但是当我尝试通过 将 uWSGI 插入 NGINX 时uwsgi_pass
,突然间所有请求在浏览器中都被截断为 9.99KB。
在阅读了有关类似截断的文章后,proxy_pass
我尝试了:
- 在我的配置文件中设置
uwsgi_buffering
为off
- 将缓冲区大小
1024k
增加到uwsgi_buffers 1024 1024k; uwsgi_buffer_size 1024k;
sendfile: off
- 检查缓冲区文件权限(其中的所有文件
/var/lib/uwsgi
都归用户www-data
和www-data
组所有,所以我认为我的权限很好。)
我保留了当前的配置,但仍然出现以下问题:
server {
listen 80;
server_name dont-tread-on-memes.controversial.io;
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/dont-tread-on-memes/dont_tread_on_memes.sock;
uwsgi_buffers 1024 1024k;
uwsgi_buffer_size 1024k;
}
}
最奇怪的是,这个问题只出现在每个第二个请求中。这一定与 NGINX 缓存有关,因为我没有使用多个 NGINX 实例或其他任何东西。然而,这一定与我的 NGINX 配置有关,因为单独运行的 uWSGI 不会出现此问题。
对于导致此问题的原因和解决方法,您有什么想法吗?
答案1
在仔细检查uwsgi
我测试的命令是否与我在文件中提供的所有选项相匹配后.ini
,我意识到我的.ini
文件包含processes = 5
,而uwsgi
我测试的命令却不包含。如果我--processes=5
在uwsgi
命令中添加,我可以在每一个命中,而不仅仅是在每一个第二个请求上。每次我uwsgi
用启动服务器时--processes=5
,第一个请求成功,第二个请求产生 500,并且所有后续请求都被截断为 9.99MB,控制台中出现以下错误:
[2017-01-08 04:16:08,959] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.4/dist-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "./flaskapp.py", line 13, in main
flag = dont_tread_on_memes.dont_me(caption)
File "./dont_tread_on_memes/__init__.py", line 30, in dont_me
return tread_on("don't {} me".format(phrase))
File "./dont_tread_on_memes/__init__.py", line 16, in tread_on
flag = BLANK_FLAG.copy()
File "/usr/local/lib/python3.4/dist-packages/PIL/Image.py", line 1010, in copy
self.load()
File "/usr/local/lib/python3.4/dist-packages/PIL/ImageFile.py", line 226, in load
"(%d bytes not processed)" % len(b))
OSError: image file is truncated (0 bytes not processed)
我怀疑这是 Pillow 和处理线程的方式的问题uwsgi
。也许每隔一个请求的行为是由于方式uwsgi
决定生成新进程并终止旧进程,或者是由于 NGINX 的缓存。无论如何,我已经修复了截断问题。
我还发现这在 StackOverflow 上,有和我一样问题的人提到了这一点。
如果其他人可以回答为什么会发生这种情况,或者回答如何既能保持此问题得到解决又能uwsgi
产生多个进程,我肯定会认为这是一个更完整的答案并接受它。
答案2
这几乎总是意味着你的图片有问题(即底部缺少数据)。我使用 PIL 处理过大于 25mb 的图片(前提是你有足够的 RAM),效果很好。解决方法在这里可能对你有用。复制并粘贴以方便阅读:
if img and img.meta_type == 'Image':
pilImg = PIL.Image.open( StringIO(str(img.data)) )
elif imgData:
pilImg = PIL.Image.open( StringIO(imgData) )
try:
pilImg.load()
except IOError:
pass # You can always log it to logger
答案3
我遇到了类似的问题。一些 javascript 文件被剪切。设置缓冲区:
uwsgi_buffers 1024 1024k;
uwsgi_buffer_size 1024k;
解决了问题