Какие есть варианты решения проблемы медленной работы сервиса аналитики при создании заказа
Что проверяют
Увидите ли вы, что проблема не в скорости аналитики, а в том, что второстепенный сервис стоит на критическом пути создания заказа. Следом обычно спрашивают, допустимо ли потерять событие аналитики и как гарантировать доставку.
Как отвечать
Начните с измерения: трейсинг через OpenTelemetry покажет, сколько времени запроса уходит на вызов аналитики, а pprof поможет, если тормозит сам сервис. Дальше варианты по возрастанию надёжности:
- таймаут и деградация: вызов через
context.WithTimeoutна десятки миллисекунд, ошибку логируем, заказ создаём. Правка минимальная, но задержка остаётся, а события теряются; - фоновая отправка в процессе: событие уходит в буферизованный канал, пул воркеров отправляет пачками. Запрос не ждёт, но при падении пода буфер пропадает, а для переполненного канала нужно заранее решить, блокировать или отбрасывать;
- брокер: публикация в Kafka или NATS JetStream, аналитика читает в своём темпе. Сервисы развязаны, пики сглаживаются;
- transactional outbox: событие пишется в таблицу
outboxтой же транзакцией, что и заказ, отдельный процесс переносит его в брокер. Ситуации «заказ есть, события нет» не бывает, чаще всего интервьюер ждёт именно этот вариант; - CDC: Debezium читает журнал базы и публикует изменения сам, код заказа про аналитику вообще не знает.
Доставка во всех надёжных вариантах получается «хотя бы один раз», поэтому на стороне аналитики нужна дедупликация по ID события.
Где спотыкаются
Запускают go sendAnalytics(r.Context(), order) без ограничений. Под нагрузкой это тысячи висящих горутин, а контекст запроса в net/http отменяется, как только обработчик вернул ответ, и отправка срывается. Нужен свой контекст с таймаутом или context.WithoutCancel.
Предлагают индексы и кэш в базе аналитики. Это ускорит сам сервис, но синхронная связка останется, и следующий сбой аналитики снова положит оформление заказов.
Публикуют в брокер отдельным вызовом после коммита заказа и не думают о двойной записи: процесс падает между двумя шагами, и событие теряется без следа.