uWSGI 引发 OSError:大型请求期间的写入错误

Posted

技术标签:

【中文标题】uWSGI 引发 OSError:大型请求期间的写入错误【英文标题】:uWSGI raises OSError: write error during large request 【发布时间】:2016-07-09 11:42:12 【问题描述】:

我的应用程序使用 nginx,在服务器端使用 uWSGI。当我做一个大请求(响应时间> 4s)时,会出现以下内容:

SIGPIPE: writing to a closed pipe/socket/fd (probably the client
    disconnected) on request _URL_ (ip XX.XX.XX.XX) !!!

uwsgi_response_writev_headers_and_body_do(): Broken pipe
    [core/writer.c line 287] during GET _URL_ (XX.XX.XX.XX)

OSError: write error

似乎 uWSGI 尝试写入流,但该流已被关闭。 当我检查 nginx 日志(error.log)时:

upstream prematurely closed connection while reading response
    header from upstream ...

当然,我的客户端(REST 客户端或浏览器)收到 502 错误。

我总是在 ~4 秒后得到这个错误。

但是,我不知道如何防止此问题。 我尝试在我的 nginx 配置文件中设置一些参数:

location my_api_url 
    [...]
    uwsgi_buffer_size 32k;
    uwsgi_buffers 8 32k;
    uwsgi_busy_buffers_size 32k;

    uwsgi_read_timeout 300;
    uwsgi_send_timeout 300;

    uwsgi_connect_timeout 60;

但问题仍然存在。 我也尝试在uWSGI配置文件(wsgi.ini)中设置这些参数:

buffer-size=8192
ignore-sigpipe=true
ignore-write-errors=true

在尝试优化响应时间之前,希望这个问题有解决方案。我没有找到在另一篇文章中工作的人。我处理大量数据,因此我的响应时间在某些情况下会在 4-10 秒之间。

希望你能帮助我:)

非常感谢。

【问题讨论】:

你是 NGINX 背后的代理还是什么?通常在客户端抢先关闭连接时会发生写入错误。 【参考方案1】:

在您上传内容时,可能会使用分块编码。 有 uWSGI 选项 --chunked-input-timeout, 默认情况下是 4 秒(它 defaults --socket-timeout 的值,即 4 秒)。

虽然理论上问题可能出在其他地方,但我建议您尝试 上述选项。另外,烦人的异常是我遇到的原因

ignore-sigpipe=true
ignore-write-errors=true
disable-write-exception=true

在我的 uWSGI 配置中(注意我提供了 3 个选项,而不是 2 个):

ignore-sigpipe 使 uWSGI 不显示 SIGPIPE 错误; ignore-write-errors 使其不显示错误 例如uwsgi_response_writev_headers_and_body_do; disable-write-exception 防止 OSError 写入生成。

【讨论】:

谢谢!真的很有帮助! 请注意,ignore-sigpipeignore-write-errorsdisable-write-exception 应根据 uWSGI 最新版本不带参数提供。见uwsgi-docs.readthedocs.io/en/latest/Options.html 要在常规(不大)请求中复制错误,请在 uWSGI 驱动的站点上打开一个页面并快速按 F5(刷新)键几次。对测试上述配置更改非常有帮助。【参考方案2】:

在我的例子中,Nginx 作为 uwsgi 的反向代理,配置 http-timeout 将服务器设置为在长时间运行的请求中正常等待。

请注意 nginx 代理声明中包含以下选项:

proxy_read_timeout 300s;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;

在网关超时方面什么都不做

【讨论】:

【参考方案3】:

我在uwsgi.ini 配置中添加了[socked-timeout=xxx],它起作用了。

【讨论】:

我没有 uwsgi.ini 文件,我只是运行 uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi:application --enable-threads -H /home/test/env --daemonize /home/test/test.log 。在这种情况下如何设置 socked-timeout? 要在命令行中添加此选项,只需添加--socket-timeout xxx

以上是关于uWSGI 引发 OSError:大型请求期间的写入错误的主要内容,如果未能解决你的问题,请参考以下文章

OSError: cannot identify image file

引发类型为“System.OutOfMemoryException”的异常

如何在 try except 块中检查某种类型的 OSError?

OSError: [WinError 740] 请求的操作需要提升

os.mkdir(path) 在目录不存在时返回 OSError

OSError: [Errno 2] 在 Django 中使用 python 子进程时没有这样的文件或目录