Я работаю над веб-сервисом, реализованным поверх nginx + gunicorn + django. Клиенты - это приложения для смартфонов. Приложение должно выполнить несколько длительных вызовов внешних API (Facebook, Amazon S3...), поэтому сервер просто ставит очередь на задание на сервер заданий (используя Celery над Redis).
Когда это возможно, как только сервер ставит в очередь задание, он сразу возвращается, а 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: в документации говорится, что асинхронные рабочие используются "Приложения, делающие длинные блокирующие вызовы (Т.е., внешние веб-сервисы)", это звучит прекрасно. В нем также говорится: "В общем, приложение должно иметь возможность использовать эти рабочие классы без изменений". Это звучит здорово. Любые отзывы об этом?
Спасибо за ваши советы.