Простая ошибка uWSGI: uwsgi_response_write_body_do() TIMEOUT

Это похоже на хорошо известную проблему с таймаутами Nginx+uWSGI, но мои настройки отличаются, и я не смог найти информацию об этом.

Я запускаю приложение Flask в uWSGI, по протоколу http (не через сокеты). Когда я запрашиваю мой API, иногда я получаю сообщение об ошибке:

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

Я получаю его чаще в "рабочее время", то есть не так часто ночью. Я запрашиваю длинные данные JSON (географические координаты, до 50 МБ), а иногда я вообще не получаю ответа, а иногда я получаю часть ответа. Это ошибки от Питона requests запрос:

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, у меня возникали те же проблемы. Так что я исключил это.

Как я могу избежать этих таймаутов?

2 ответа

Я также использую nginx + uwsgi для создания большого файла и встречаю ту же проблему. Я решил эту проблему, отключив буфер временных файлов uwsgi в директиве использования nginx uwsgi_max_temp_file_size 0;,

Я думаю, что скорость передачи от nginx к клиенту намного ниже, чем от uwsgi до nginx. А буфер nginx заполнен, поэтому uwsgi ждет много времени, прежде чем nginx сможет освободить место для получения новых данных, и это заставит uwsgi запрос на запись.

Я публикую блог для анализа этой проблемы в своем блоге.

В исходном коде 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определяется вuwsgi.hкак:

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

Не копая глубже, я не могу быть на 100% уверен, чтоsocket_timeoutздесь то же самое, что и вариант uwsgi.

Однако я могу сказать, что добавление--socket-timeout 1200к моему вызову uwsgi удалось найти вполне надежный способ воспроизвестиTIMEOUT !!!ошибка при загрузке довольно большого файла из установки Python→uwsgi→nginx через медленное соединение.

Поэтому я думаю, что увеличение--socket-timeout— лучший вариант, хотя я не уверен, могут ли также потребоваться некоторые другие настройки буферизации в конфигурации nginx.

Другие вопросы по тегам