Простая ошибка 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.