Я работаю над веб-службой, реализованной поверх nginx + gunicorn + django . Клиентами являются приложения для смартфонов. Приложению необходимо сделать несколько длительных вызовов внешних API (Facebook, Amazon S3... ), поэтому сервер просто ставит задание в очередь на сервер заданий (, используя Celery через Редис).
По возможности, как только сервер поставит задание в очередь, он сразу же вернется, и соединение HTTP будет закрыто. Это прекрасно работает и позволяет серверу выдерживать очень высокую нагрузку.
client server job server
. | |
. | |
|------HTTP request----->| |
| |--------queue job------>|
|<--------close----------| |
. | |
. | |
Но в некоторых случаях клиенту необходимо получить результат сразу после завершения работы. К сожалению, после закрытия HTTP-соединения сервер не может связаться с клиентом. Одним из решений было бы полагаться на то, что клиентское приложение будет опрашивать сервер каждые несколько секунд, пока задание не будет завершено. Я хотел бы избежать этого решения, если это возможно, в основном потому, что это будет препятствовать реактивности службы,а также потому, что это загрузило бы сервер множеством ненужных запросов опроса.
Короче говоря, я хотел бы поддерживать HTTP-соединение в рабочем состоянии, ничего не делая (, за исключением, возможно, отправки пробела время от времени, чтобы поддерживать TCP-соединение, просто , как это делает Amazon S3 )., пока задание не будет выполнено и сервер не вернет результат.
client server job server
. | |
. | |
|------HTTP request----->| |
| |--------queue job------>|
|<------keep-alive-------| |
| [...] | |
|<------keep-alive-------| |
| |<--------result---------|
|<----result + close-----| |
. | |
. | |
Как я могу эффективно реализовать длительные HTTP-соединения, предполагая, что сервер находится под очень высокой нагрузкой (, это еще не так, но цель - выдерживать максимально возможную нагрузку с сотнями или тысячами запросов. в секунду )?
Перенос фактических заданий на другие серверы должен обеспечить низкую загрузку ЦП на сервере, но как избежать накопления процессов и использования всей оперативной памяти сервера или отбрасывания входящих запросов из-за слишком большого количества открытых соединений?
Вероятно, это в основном вопрос правильной настройки nginx и gunicorn. Я немного читал об асинхронных воркерах, основанных на гринлетах в gunicorn :. в документации говорится, что асинхронные рабочие процессы используются «приложениями, выполняющими длительные блокирующие вызовы (т. е. внешними веб-сервисами)", звучит идеально. Там также говорится: "В общем, приложение должно иметь возможность использовать эти рабочие классы без каких-либо изменений ". Звучит великолепно. Есть отзывы по этому поводу?
Спасибо за ваши советы.