普通 uWSGI 错误:uwsgi_response_write_body_do() 超时

普通 uWSGI 错误:uwsgi_response_write_body_do() 超时

这看起来像是 Nginx+uWSGI 超时的一个众所周知的问题,但我的设置不同,我找不到有关它的信息。

我在 uWSGI 上运行 Flask 应用,使用 http 协议(不是套接字)。当我查询 API 时,有时会收到错误:

uwsgi_response_write_body_do() TIMEOUT !!!
IOError: : write error

我在“工作时间”收到此错误的频率更高,即晚上收到此错误的频率较低。我查询的是长 JSON 数据(地理坐标,最大 50 MB),有时完全没有响应,有时只收到部分响应。以下是 Pythonrequests请求中的错误:

requests.exceptions.ConnectionError: ('Connection aborted.', error(104, 'Connection reset by peer'))

requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRead(0 bytes read)', IncompleteRead(0 bytes read))

ValueError: Expecting object: line 1 column 5590371 (char 5590370)

ValueError: Unterminated string starting at: line 1 column 20998536 (char 20998535)

ValueError: end is out of bounds

# when I set `timeout=None` in Python
requests.exceptions.ReadTimeout: HTTPConnectionPool(host='mydomain.com', port=80): Read timed out. (read timeout=None)

连接是通过普通 HTTP(无 S)进行的。我的 uWSGI 配置如下:

[uwsgi]
module = run:app
pidfile = /tmp/app.pid
logto = /var/log/uwsgi/%n.log

master = true
processes = 2

http-socket = 0.0.0.0:someport
http-timeout = 300

die-on-term = true

我使用 运行此程序uwsgi /path/to/inifile。没有 Nginx,但实际上之前使用 Nginx 时,我也遇到过同样的问题。所以我排除了这个。

我怎样才能避免这些超时?

答案1

我也使用 nginx + uwsgi 生成大文件,并遇到同样的问题。我通过在 nginx 使用指令中禁用 uwsgi 临时文件缓冲区解决了此问题uwsgi_max_temp_file_size 0;

我认为从 nginx 到客户端的传输速度远远慢于从 uwsgi 到 nginx 的速度。而且 nginx 的缓冲区已满,因此 uwsgi 需要等待很长时间才能有空间让 nginx 接收新数据,这会导致 uwsgi 的写入请求超时。

我在我的博客中发表了一篇博客来分析这个问题。

答案2

在 uwsgi 源代码中,只有两处出现该错误字符串。两者周围的代码看起来相似,因此让我们专注于其中之一

            ret = uwsgi_wait_write_req(wsgi_req);
            if (ret < 0) { wsgi_req->write_errors++; return -1;}
            if (ret == 0) {
        // here we use the parent name
                    uwsgi_log("uwsgi_response_write_body_do() TIMEOUT !!!\n");
                    wsgi_req->write_errors++;
                    return -1;
            }

看起来如果的返回值uwsgi_wait_write_req为零,则会触发TIMEOUT !!!错误。uwsgi_wait_write_req定义在uwsgi.h作为:

#define uwsgi_wait_write_req(x) uwsgi.wait_write_hook( \
    x->fd, uwsgi.socket_timeout) ; x->switches++

如果不深入挖掘,我不能 100% 确定这里socket_timeoutuwsgi--socket-timeout选项

但是,我可以说,添加--socket-timeout 1200到我的 uwsgi 调用确实修复了一种非常可靠的方法,可以TIMEOUT !!!在通过慢速连接从 Python→uwsgi→nginx 设置下载相当大的文件时重现错误。

因此我认为增加--socket-timeout是最好的选择,尽管我不确定是否还需要 nginx 配置中的其他缓冲设置。

相关内容