Является ли Kafka хорошей идеей для соединения REST API с Worker, который выполняет большие вычисления по заданию в очереди?

Является ли Kafka хорошей идеей для соединения REST API с Worker, который выполняет большие вычисления по заданию в очереди?
Является ли Kafka хорошей идеей для соединения REST API с Worker, который выполняет большие вычисления по заданию в очереди?

В настоящее время у нас есть сервис REST API (назовем его A), написанный на Python, который запускает различные тяжелые вычислительные задания для Worker (W), также написанного на Python. Оба сервиса связаны между собой с помощью самописного PostgreSQL queue lib.

Вот как они общаются на данный момент:

 1. Call POST request to service A to create a Job in PG Queue
 2. Worker takes a job from Queue and runs calculations
 3. After a successful calculations the worker saves results in the shared DB 
- 
 1. External service B requests every N seconds service A to take the data calculated in the W by job id
 2. Service A observes shared DB and returns the data once the worker is finished (status=Done for a particular job)

Мы решили переписать Python-сервис A на Node.JS (NestJS) и всячески улучшить текущую реализацию. Как вы могли заметить, там есть строка External service B requests every N seconds. Мы хотим избавиться и от этого шаблона и использовать что-то более эффективное и производительное для данного случая.

1. Концепция с использованием Kafka

Первая идея - использовать какой-нибудь сервис очередей сообщений, например Kafka:

Мне нравится этот подход, поскольку у нас есть отдельный рабочий, который выполняет только некоторые вычисления (задания), и Kafka, который играет роль распределения сообщений между сервисами. Такой подход также позволяет избавиться от интервальных/опросных запросов для получения актуальных данных.

В то же время у него есть несколько возможных недостатков:

  • Представьте, что Worker работает только в одном потоке и, соответственно, может выполнять одно задание за раз. Как обрабатывать несколько сообщений одновременно из Kafka в Worker, если уже есть запущенное задание? Нужно ли создавать RAM Queue или Kafka справится с этими задачами?
  • Что если Kafka или сервис, потребляющий сообщения, внезапно отключится, будут ли потеряны переданные данные?
  • Может быть, вместо Kafka использовать другой подходящий MQ, например RabbitMQ?

2. Концепция использования PG Queue ... с Kafka

Поскольку мы переписываем сервис с нуля, используя новую технологию, мы можем улучшить оригинальный подход, заменив интервальные запросы для получения данных на Kafka. Таким образом, схема взаимодействия будет выглядеть следующим образом:

 1. External service B consumes all messages from a particular topic
 2. Service A observes DB and sends data to the topic once the worker is finished (status=Done on the job)

Подход с использованием общей базы данных и очереди Postgres кажется мне более безопасным и контролируемым, но в то же время подход с использованием Kafka в качестве общего брокера сообщений кажется более современным и устойчивым.

Есть какие-нибудь мысли по этому поводу? Может быть, есть лучший подход к этой проблеме?

Вы правильно определили большую неэффективность:

External service B requests every N seconds

Любой вид длительного опроса или непрерывного опроса будет неэффективным, если нормальная продолжительность работы неизвестна.

Согласно вашей диаграмме, как только рабочий закончит вычислять результат, он может сделать две вещи:

  1. Сохраняйте результаты работы где-нибудь (в базе данных, в ведре s3, даже в самом Kafka с политикой длительного хранения).
  2. Уведомлять других о том, что работа выполнена (Kafka, AWS SNS и т.д.).

Это будет гораздо более эффективный дизайн, который также не слишком сложно реализовать. Вы должны чувствовать себя уверенно, чтобы идти по этому пути, если вам удобно изучать детали нижнего уровня Kafka SDK на вашем языке.


LetsCodeIt, 29 декабря 2022 г., 01:39