Я работаю в службе, которая обрабатывает некоторые входные данные (скажем, параметры для расчета цены) от имени пользователя и генерирует выходные данные (скажем, рассчитанная цена).Расчет может занять до 20 секунд.
Текущая ситуация
Сейчас у меня есть вычисления, доступные через HTTP-вызов.Например,
curl -X POST \
-H "Content-Type: application/json" \
--data '{"param1": "value"}' \
https://api.my-service.com/v1/calculate
Я получаю результат, подобный
{ "price": 55.00 }
Проблема
Мы сталкиваемся с проблемами классической масштабируемости.Когда мы достигаем дневного пика и имеем несколько сотен одновременных запросов, время отклика резко возрастает.Поэтому я хотел бы реализовать очередь с запросами на расчет цены.
Возможные решения
Я считаю, что использование очереди сообщений - наш путь вперед.Я не хочу вдаваться в конкретные технологии здесь, но мы экспериментируем с RabbitMQ прямо сейчас.
В общем, архитектура будет выглядеть так:
client
▲
| HTTP
▼
------------------ -------------------
| Producer (service| | Consumer (service |
| requesting price | --> RabbitMQ Queue --> | calculating price)|
| calculation) | | | | | | | |
------------------ -------------------
Нам нужнополучить результат расчета цены обратно пользователю в веб-браузере или на мобильных устройствах.Поэтому нам нужно уведомить производителя, как только потребитель завершит вычисление.
Вариант 1: оставить запрос HTTP открытым до тех пор, пока потребитель не выполнит
Мы можем построить вторую очередь, в которой потребитель может публиковатьсообщение после расчета.Производитель получит это сообщение и отобразит результаты для пользователя:
client
▲
| HTTP
▼
------------------ -------------------
| Producer (service| | Consumer (service |
| requesting price | --> RabbitMQ Queue --> | calculating price)|
| calculation) | | | | | | | |
------------------ -------------------
<-- Feedback Queue --
Хотя это работает и его легко реализовать, его слепая реализация, как это будет означать, что мы по-прежнему будем держать HTTP-запрос открытыммежду клиентом и производителем услуг.Это похоже на большие затраты ресурсов и похоже на то, что мы на самом деле не решаем нашу проблему.
Вариант 2: опрос результатов
Второй вариант: мы можем отменить запрос от клиента к производителюи закройте HTTP-соединение в этой точке.Затем клиент может регулярно опрашивать обновления от производителя, чтобы узнать, завершилось ли вычисление:
client
| HTTP: ▲
| calculate | HTTP: Poll until
| price! | calculation has
▼ | finished
------------------ -------------------
| Producer (service| | Consumer (service |
| requesting price | --> RabbitMQ Queue --> | calculating price)|
| calculation) | | | | | | | |
------------------ -------------------
<-- Feedback Queue --
Мне нравится этот подход, поскольку он минимизирует накладные расходы ввода-вывода и устраняет любые проблемы тайм-аута HTTP.Но кажется, что это лишь нерешительная реализация шаблона обмена сообщениями.
Вопрос
Я уверен, что должны быть другие, кто реализовал подобный вариант использования и внедрил любое решение.Я ищу ваши уроки / ошибки и ваши рекомендации.