2016-09-29 6 views
17

У меня есть приложение для приложения Django, и мне было интересно, можно ли nginx распространять прервать/закрыть uwsgi/Django.Пропаганда http abort/close from nginx to uwsgi/Django

В основном я знаю, что nginx знает о преждевременном прерывании/закрытии, поскольку по умолчанию он равен uwsgi_ignore_client_abort, и вы получаете ошибки nginx 499 в ваших журналах nginx, когда запросы прерываются/закрываются до отправки ответа. Как только uwsgi завершает обработку запроса, он выдает «IO Error», когда он возвращается, чтобы вернуть ответ nginx.

Включение uwsgi_ignore_client_abort в положение "on" только заставляет nginx не знать о прерывании/закрытии и удаляет uwsgi "IO Errors", потому что uwsgi все равно может записать обратно в nginx.

Мой вариант использования: у меня есть приложение, в котором люди просматривают некоторые результаты ajax очень быстро, и поэтому, если быстрая страница через я прерываю ожидающий запрос ajax для страницы, которую они пропустили, это позволяет клиенту быть чистым и эффективным , Но это ничего не делает для серверной части (uwsgi/Django), потому что они все равно должны обрабатывать каждый отдельный запрос, даже если ничего не ждет ответа.

Теперь очевидно, что могут быть определенные страницы, где я не хочу, чтобы запрос был преждевременно прерван по какой-либо причине. Но я использую сельдерей для длительных запросов, которые могут попасть в эту категорию.

Это возможно? uwsgi's Настройки hariakari заставляют меня думать, что это на каком-то уровне .... просто не могу понять, как это сделать.

+0

Почему бы не спросить списки рассылки uWSGI и NGINX? – silpol

+2

Да, неплохая идея. Я пробовал IRC-канал uWSGI, но я не думаю, что я очень хорошо объяснил себя. Я думаю, может быть, я снова смогу попробовать, возможно, связавшись с этим вопросом. – byoungb

+1

Любопытно, что uwsgi имеет функцию is_connected. В случаях, когда вы завершили соединение, возвращает ли эта функция False? Похоже, что проблема действительно на стороне uwsgi, так как в документах Nginx указано, что настройки proxy_ignore_client_abort и uwsgi_ignore_client_abort оба отключены глухотой. – jaywhy13

ответ

2

Теперь очевидно, что могут быть определенные страницы, где я не хочу, чтобы запрос был преждевременно прерван по какой-либо причине.

Это как раз проблема, связанная с тем, что это происходит так или иначе.

  • Очевидно, что вы не можете продолжать расходы ресурсов системы обработки соединения, которое с тех пор было прервано, например, дорогостоящая операцией поиска.

  • Но тогда, возможно, соединение было достаточно важным, что его еще нужно обработать, даже если клиент отключился.

    • Е.Г., тот же дорогостоящая операция поиска, но один, что на самом деле не мандант, и будет кэшировать Nginx для всех последующих клиентов тоже.

    • Возможно, операция, которая изменяет состояние вашего приложения - вы явно не хотите, чтобы ваше приложение имело несогласованное состояние!

Как упоминалось выше, проблема с uWSGI, а не с NGINX. Тем не менее, вы не можете uWSGI автоматически решить, каково было ваше намерение, без того, чтобы вы открыли такое намерение для uWSGI.

И как именно вы раскроете свое намерение в своем коде? Целая группа языков программирования не поддерживает многопоточные и/или асинхронные модели программирования, что делает ее полностью нетривиальной для отмены операций.

Как таковое, здесь нет магического решения.Even the concurrency-friendly programming languages like Golang are having issues around the WithCancelcontext - вам, возможно, придется передавать его во всех вызовах функций, которые могут блокироваться, что делает код очень уродливым.

Вы уже используете вышеуказанный контекст, проходящий в Django? Если нет, то решение некрасиво, но очень просто - в любое время вы можете четко прервать запрос, проверить, является ли клиент по-прежнему связан с uwsgi.is_connected(uwsgi.connection_fd()):

5

Мой случай использования что у меня есть приложение, в котором люди просматривают некоторые результаты ajax очень быстро, и поэтому, если быстро перейти на страницу, я отменяю ожидающий запрос ajax на пропущенную страницу, это позволяет клиенту быть чистым и эффективным.

Отмена запроса AJAX на стороне клиента осуществляется через XMLHttpRequest.abort(). Если запрос еще не отправлен, когда вызывается abort(), запрос не будет выходить. Но если запрос был отправлен, сервер не будет знать, что запрос был прерван. Соединение не будет закрыто, никаких сообщений, отправленных на сервер, ничего не будет. Если вы хотите, чтобы сервер знал, что запрос больше не нужен, вам в основном нужно найти способ идентифицировать запросы, чтобы при первоначальном запросе вы получили для него идентификатор. Затем через другой запрос AJAX вы можете указать , чтобы сервер сказал, что предыдущий запрос должен быть отменен. (Если вы будете искать вопросы abort()like this one и поиск «сервера» вы найдете объяснения, говоря то же самое.)

Обратите внимание, что uwsgi_ignore_client_abort является то, что имеет дело с закрытием соединения на уровне TCP. Это совсем другое дело - отменить запрос AJAX. Как правило, нет никаких действий, которые вы можете предпринять в JavaScript, который будет влечет за собой закрытие TCP-соединения. Браузер оптимизирует создание и уничтожение соединений в соответствии с его потребностями. Только сейчас, я сделал это:

  1. Я использовал lsof, чтобы проверить, есть ли какой-либо процесс подключения к example.com. Их не было. (lsof - это утилита * nix, которая позволяет отображать открытые файлы. Сетевые подключения - это «файлы» в * nix.)

  2. Я открыл страницу на example.com в Chrome. lsof показал соединение и процесс, который открыл его.

  3. Затем я закрыл страницу.

  4. Я опросил lsof, чтобы узнать, было ли обнаружено ранее обнаруженное соединение. Он оставался открытым около минуты после того, как я закрыл страницу, хотя не было никакой реальной необходимости поддерживать соединение открытым.

И нет количества манипуляций с настройками uswgi, которые сделают это знать прерывает осуществляются через XMLHttpRequest.abort()

Использования сценарий вы дали был один, где пользователи были пейджинг быстро через некоторые Результаты.Я вижу две возможности для описания вопросов, заданных в вопросе:

  1. Пользователь ждет обновления до дальнейшего поискового вызова. Например, Алиса просматривает список имен пользователей, отсортированных по алфавиту для пользователя «Zeno», и каждый раз, когда отображается новая страница, она видит, что имя отсутствует и страницы опущены. В этом случае нет ничего, что можно было бы прервать, поскольку действие пользователя зависит от того, был ли обработан запрос . (Пользователь должен увидеть новую страницу, прежде чем принимать решение.)

  2. Пользователь просто пролистывает страницы, не дожидаясь обновления. Алиса снова ищет «Зено», но она считает, что она будет на последней странице, поэтому нажмите, щелкните, щелкните по ней. В этом случае вы можете отменить запросы, сделанные на сервере. Затем нажимается кнопка следующей страницы, увеличивайте число страниц, которые должны отображаться пользователю, но не отправляйте запрос сразу. Вместо этого вы ждете небольшой задержки после того, как пользователь перестанет нажимать кнопку, чтобы отправить запрос с номером страницы final, и поэтому вы делаете один запрос вместо дюжины. Here - пример debounce, выполненного для поиска DataTables.

+0

Интересно, потому что с моими испытаниями это работало на некотором уровне ... (я мог посмотреть в журналах uwsgi и увидеть ошибку для каждого прерванного запроса ajax). Интересно, связано ли это с моими настройками keepalive или тем фактом, что я мой фактический путь подключения - haproxy -> nginx -> uwsgi -> django. – byoungb

+0

Единственные настройки, о которых я знаю, могут сделать корреляцию XHR с закрытием соединения на стороне браузера. Я помню, что видел документацию о настройках, которые могли бы изменить, как часто браузер закрывает соединения. Предположительно, можно было бы установить настройки в конечном итоге с помощью браузера, который будет закрывать соединение почти сразу после выхода из строя XHR. Обратите внимание, что это настройки, предназначенные для разработчиков, а не то, что люди обычно используют. Я также мог видеть, как прокси-сервер может закрывать соединения чаще, чем браузер. – Louis