Какие способы уведомления второго сервиса о событии в первом сервисе существуют
Что проверяют
Понимаете ли вы разницу между синхронным вызовом и асинхронным событием и что происходит, когда второй сервис лежит. Следом почти всегда спрашивают, как не потерять событие, если база уже закоммитила изменение, а брокер недоступен.
Как отвечать
Разложите способы по степени связанности:
- HTTP-вызов или webhook: первый сервис дёргает API второго через
HttpClientизIHttpClientFactory. Просто, но сервисы связаны по времени, поэтому нужны таймауты и повторы, в .NET 8 и новее черезMicrosoft.Extensions.Http.Resilienceповерх Polly; - gRPC: быстрее и строго типизирован через
.proto, но это тот же синхронный вызов. Server streaming подходит, когда второй сервис держит поток и ждёт изменений; - брокер сообщений: RabbitMQ, Kafka, Azure Service Bus. Очередь отдаёт сообщение одному потребителю, топик каждой подписке. Из .NET работают через MassTransit, Wolverine или официальные клиенты;
- transactional outbox: событие пишется в таблицу
outboxв той же транзакции, что и данные, а фоновыйBackgroundServiceпубликует его в брокер; - CDC: изменения читаются из журнала базы (Debezium, встроенный CDC в SQL Server) и превращаются в события без правок кода первого сервиса;
- опрос: второй сервис сам периодически спрашивает изменения. Задержка выше, зато без брокера.
Дальше про гарантии. Брокеры дают доставку «хотя бы один раз», поэтому потребитель обязан быть идемпотентным: хранить идентификаторы обработанных сообщений или делать операции повторяемыми.
Где спотыкаются
Сохраняют сущность через SaveChangesAsync, а потом публикуют событие отдельным вызовом. Процесс упал между двумя шагами, и второй сервис никогда не узнает об изменении.
Называют Event Sourcing способом уведомления. Это модель хранения состояния, а доставку событий наружу всё равно решает брокер или outbox.
Обещают exactly-once и общий порядок. В Kafka порядок гарантирован только внутри партиции, а дубли при повторной доставке бывают в любом брокере.