Асинхронный обратный вызов с использованием Scala и Play2 или спрей
У меня есть проблема проектирования систем, о которой я хотел бы получить отзывы сообщества.
Базовая структура системы:
[Клиент] ---HTTP-POST-> [Служба REST] ---> [Очередь] ---> [Процессоры]
- [Клиент] отправляет JSON [REST Service] для обработки.
- На основе запроса [Rest Services] отправляет данные в различные очереди, которые будут получены различными процессорами, написанными на разных языках и запущенными в разных процессах.
- Работа распараллеливается на каждом процессоре, но обработка может занять до 30 секунд. Время на обработку зависит от сложности данных и не может быть ускорено.
- Результат не может быть передан обратно клиенту, поскольку он завершен, поскольку существует последний этап постобработки, который может быть выполнен только после завершения всех подэтапов.
Ключевая задача: после завершения постобработки клиент должен либо:
- отправлять результаты после ожидания клиента
- быть уведомленным асинхронно о том, что задание выполнено и ему передан идентификатор для запроса окончательного результата
Требования к дизайну
Я не хочу блокировать [Служба REST]. Он должен принять входящий запрос, направить данные в соответствующие очереди для обработки в других процессах, а затем сразу же стать доступным для следующего входящего запроса.
Обычно я использовал бы актеров и / или фьючерсы / обещания, чтобы [Служба REST] не блокировалась при ожидании завершения фоновых рабочих. Проблема здесь заключается в том, что работники, выполняющие фоновую работу, работают в отдельных процессах / виртуальных машинах и пишутся в различных технологических стеках. Для передачи этих сообщений между гетерогенными системами и обеспечения целостности времени жизни запроса используется долговременная очередь (не для передачи сообщений в памяти или RPC).
Конечная точка рассмотрения, для того чтобы масштабировать, существует балансировка нагрузки [REST Services] и [Processors] в соответствующих пулах. Поэтому, поскольку сообщения от [Службы REST] на [Процессор] необходимо отправлять асинхронно через очередь (и все, что выполняется, - это отдельные процессы), нет способа сопоставить работу, выполненную в фоновом режиме [Процессор], обратно. в его исходный вызывающий экземпляр [REST Service], чтобы вернуть окончательно обработанные данные в сообщении обещания или актера и, наконец, передать ответ исходному клиенту.
Итак, вопрос в том, как сделать это соотношение? Как только вся фоновая обработка завершена, мне нужно вернуть результат клиенту либо через долгожданный ответ, либо через уведомление (я не хочу использовать что-то вроде UrbanAirship, так как большинство клиентов являются браузерами или другими службами.
Я надеюсь, что это понятно, если нет, пожалуйста, попросите разъяснений.
Изменить: Возможное решение - мысли?
Я думаю, что я передаю Спрос RequestContext любому субъекту, который затем может ответить клиенту (не обязательно должен быть исходным субъектом, получившим HTTP-запрос). Если это так, могу ли я кешировать RequestContext, а затем использовать его позже для асинхронной отправки ответа соответствующему клиенту, используя этот кешированный RequestContext, когда обработка будет завершена?
1 ответ
Ну, это не самое лучшее, потому что это требует больше работы от вашего Клиента, но похоже, что вы хотите реализовать веб-крючок. Так,
[Клиент] --- POST -> [Служба REST] ---> [Расчеты] ---> POST [Клиент]
[Клиент] --- ПОЛУЧИТЬ
Для объяснения: Клиент отправляет запрос POST к вашему сервису. Ваша служба затем выполняет любую необходимую обработку. После завершения ваша служба отправит HTTP-POST на URL, который Клиент уже установил. С этими данными POST клиент получит необходимую информацию для выполнения запроса GET для завершенных данных.