Nginx дает uWSGI очень старые запросы?

Я наблюдаю странную ситуацию, когда Nginx или uwsgi, похоже, создают длинную очередь входящих запросов и пытаются обработать их задолго после истечения времени ожидания клиентского соединения. Я хотел бы понять и остановить это поведение. Вот больше информации:

Моя настройка

Мой сервер использует Nginx для передачи запросов HTTPS POST в uWSGI и Flask через файловый сокет Unix. У меня есть в основном конфигурации по умолчанию на все.

У меня есть клиент Python, отправляющий 3 запроса в секунду на этот сервер.

Эта проблема

После запуска клиента в течение примерно 4 часов клиентский компьютер начал сообщать о том, что для всех соединений истекло время ожидания. (Он использует библиотеку запросов Python с 7-секундным таймаутом.) Примерно через 10 минут поведение изменилось: соединения начали обрываться с 502 Bad Gateway.

Я выключил клиент. Но в течение примерно 10 минут ПОСЛЕ выключения клиента журналы uWSGI на стороне сервера показывали, что uWSGI пытается ответить на запросы от этого клиента! А также top показал uWSGI, используя 100% ЦП (25% на одного работника).

В течение этих 10 минут каждый uwsgi.log запись выглядела так:

Thu May 25 07:36:37 2017 - SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request /api/polldata (ip 98.210.18.212) !!! Thu May 25 07:36:37 2017 - uwsgi_response_writev_headers_and_body_do(): Broken pipe [core/writer.c line 296] during POST /api/polldata (98.210.18.212) IOError: write error [pid: 34|app: 0|req: 645/12472] 98.210.18.212 () {42 vars in 588 bytes} [Thu May 25 07:36:08 2017] POST /api/polldata => generated 0 bytes in 28345 msecs (HTTP/1.1 200) 2 headers in 0 bytes (0 switches on core 0)

И Nginx error.log показывает многое из этого:

2017/05/25 08:10:29 [error] 36#36: *35037 connect() to unix:/srv/my_server/myproject.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 98.210.18.212, server: example.com, request: "POST /api/polldata HTTP/1.1", upstream: "uwsgi://unix:/srv/my_server/myproject.sock:", host: "example.com:5000"

Примерно через 10 минут активность uWSGI прекращается. Когда я снова включаю клиент, Nginx с радостью принимает запросы POST, но uWSGI выдает одну и ту же ошибку "запись в закрытую трубу" при каждом запросе, как будто он каким-то образом не работает. Перезапуск Docker-контейнера веб-сервера не устраняет проблему, но перезагрузка хост-машины устраняет ее.

Теории

В конфигурации по умолчанию Nginx -> socket -> uWSGI есть длинная очередь запросов без тайм-аута? Я просмотрел документы uWSGI и увидел множество настраиваемых тайм-аутов, но все они по умолчанию составляют около 60 секунд, поэтому я не могу понять, как я вижу запросы 10-минутной давности. Я не изменил никаких настроек времени ожидания по умолчанию.

Приложение использует почти все 1 ГБ ОЗУ на моем маленьком dev-сервере, поэтому я думаю, что ограничение ресурсов может быть причиной такого поведения.

В любом случае, я бы хотел изменить свою конфигурацию, чтобы запросы старше 30 секунд отбрасывались с ошибкой 500, а не обрабатывались uWSGI. Буду признателен за любые советы о том, как это сделать, и теории о том, что происходит.

2 ответа

Решение

Похоже, что это проблема вниз по течению со стороны uWSGI.

Похоже, ваш бэкэнд-код может быть неисправен в том смысле, что он обрабатывает запросы слишком долго, не реализует какого-либо ограничения скорости для запросов и не отлавливает должным образом, если какое-либо из базовых соединений было разорвано (следовательно, вы Вы получаете ошибки, которые ваш код пытается записать в закрытые конвейеры, и, возможно, даже начать обрабатывать новые запросы еще долго после того, как базовые соединения были разорваны).

  • Согласно http://lists.unbit.it/pipermail/uwsgi/2013-February/005362.html/ 005362.html, вы можете прервать обработку в вашем бэкэндеif not uwsgi.is_connected(uwsgi.connection_fd()),

  • Возможно, вы захотите изучить https://uwsgi-docs.readthedocs.io/en/latest/Options.html.

  • В крайнем случае, согласно Re: Понимание функциональности "proxy_ignore_client_abort" (2014), вы можете захотеть изменитьuwsgi_ignore_client_abort от off в on для того, чтобы не отбрасывать текущие соединения uWSGI, которые уже были переданы в восходящий поток (даже если клиент впоследствии отключается), чтобы не получать ошибки закрытого канала от uWSGI, а также для принудительного применения любых возможных ограничений одновременного соединения в nginx само по себе (в противном случае соединения с uWSGI будут прерваны nginx, если клиент отключится, и nginx не будет иметь ни малейшего представления, сколько запросов ставится в очередь в uWSGI для последующей обработки).

Похоже, DoS-атака на Nginx uWSGI возвращает 100% загрузку ЦП с Nginx 502, 504, 500. Подделка IP распространена в DoS-атаке. Исключить, проверив логи.

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