Получить доступ

Spring Cloud Stream

Binder abstraction, functional model, bindings, consumer groups, partitioning и trade-offs поверх Kafka/RabbitMQ.

Идея: функция отдельно от брокера

Spring Cloud Stream позволяет писать обработчики событий так, чтобы код не зависел от конкретного брокера. Приложение описывает, что делать с сообщением, а связь с Kafka или RabbitMQ берёт на себя binder — адаптер под конкретный брокер. Сменить брокер можно заменой зависимости и конфигурации, не трогая бизнес-код.

У абстракции есть предел: модель общая для всех брокеров, поэтому специфичные возможности (ручное управление offset в Kafka, сложная маршрутизация RabbitMQ, задержанная доставка) приходится настраивать через свойства конкретного binder, а иногда они недоступны вовсе.

Функциональная модель

В современных версиях обработчики — это обычные бины функциональных типов Java: Supplier публикует сообщения, Function принимает и отдаёт результат дальше, Consumer только принимает. Имя бина задаёт имя привязки (binding), а в конфигурации привязка связывается с топиком или очередью.

@Bean
Consumer<OrderPaid> bill() {
    return event -> billing.handle(event);
}
spring:
  cloud:
    stream:
      bindings:
        bill-in-0:
          destination: orders.paid    # топик или exchange
          group: billing              # группа потребителей

Код получается компактным, но связь между функцией и топиком живёт в конфигурации. Чтобы через полгода было понятно, кто что читает, имена привязок и топиков стоит держать единообразными.

Destination и group

Destination — логическое имя места доставки: топик Kafka или exchange RabbitMQ. Group — группа потребителей: экземпляры одного сервиса с одной группой делят сообщения между собой, а разные группы получают каждая свою копию потока. Для Kafka группа становится group.id и хранит свой прогресс чтения.

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

Партиционирование

Чтобы события одной сущности обрабатывались по порядку, их нужно направлять в одну партицию. В Cloud Stream для этого задают выражение ключа партиционирования (partition-key-expression, например идентификатор заказа) и число партиций.

Абстракция не отменяет понимания брокера: в Kafka порядок гарантирован только внутри партиции, а в RabbitMQ партиции эмулируются набором очередей с маршрутизацией — и семантика у них другая.

Когда лучше без Cloud Stream

Если сервису нужны тонкие возможности конкретного брокера — ручной коммит offset, транзакции Kafka, собственная стратегия повторов и DLT, — напрямую Spring Kafka или Spring AMQP обычно понятнее: меньше слоёв, проще отладка, документация брокера применима без перевода.

Cloud Stream хорош там, где у компании много однотипных сервисов-обработчиков и важно единообразие. Но он не заменяет знания брокера: ошибки с порядком, группами и повторной доставкой всё равно придётся понимать на уровне Kafka или RabbitMQ.

Как отвечать на собеседовании

Объясните идею binder: бизнес-код отдельно, брокер — в конфигурации. Покажите функциональную модель (Supplier, Function, Consumer) и как привязка связывает функцию с топиком.

Обязательно назовите ловушку с отсутствующей группой и роль ключа партиционирования для порядка. Закончите границей применимости: для типовых обработчиков Cloud Stream удобен, а когда нужны специфичные возможности брокера, честнее использовать Spring Kafka или Spring AMQP напрямую.

Вопросы по теме

Читайте также

Закрытая бета

Знать тему — половина дела

На живом собеседовании sotto слышит вопрос интервьюера и показывает короткий ответ и план. Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем