Как локализовать проблему в микросервисной архитектуре при ошибке в запросе на бэкенд
Что проверяют
Есть ли у вас метод, а не перебор «посмотрю логи, спрошу разработчика». Интервьюеру важно, сможете ли вы назвать конкретный сервис и завести дефект на нужную команду. Следом спрашивают, что вы положите в баг-репорт и как поймёте, что проблема не в тестовом стенде.
Как отвечать
Идите от входа по цепочке вызовов:
- ответ: код статуса и тело. 502 или 504 от шлюза чаще значат, что упал или не успел сервис за ним, 500 со стеком приходит от самого приложения, 4xx говорит о запросе или контракте;
- идентификатор запроса: найдите в заголовках
X-Request-IDили trace id изtraceparent(стандарт W3C Trace Context). Это ключ ко всему остальному; - трассировка: по trace id в Jaeger, Zipkin или Grafana Tempo видно дерево спанов: какой сервис кого вызвал, где ошибка и где ушло время;
- логи: тот же id в Kibana или Loki покажет логи всех сервисов по этому запросу. Ищите первую ошибку по времени, а не последнюю;
- метрики: в Grafana проверьте, выросла ли доля ошибок у сервиса и совпадает ли это с деплоем;
- изоляция: повторите вызов к подозреваемому сервису напрямую через Postman или
curl, минуя шлюз, и сравните с контрактом в OpenAPI. Соседние сервисы можно заменить заглушкой в WireMock.
Если в цепочке есть Kafka или RabbitMQ, проверьте, дошло ли сообщение, не лежит ли оно в DLQ и не отстаёт ли консьюмер. Без трассировки выручат время запроса и версии сервисов на стенде.
В баг-репорт кладите окружение, время, trace id, запрос и ответ, сервис, где возникла ошибка, и версию его сборки.
Где спотыкаются
Записывают «бэкенд вернул 500» и отдают первой попавшейся команде. Без trace id и времени разработчику придётся повторять вашу работу.
Считают виновником сервис, в чьём логе ошибка видна. Часто он лишь пробросил исключение соседа или упал по таймауту, пока тот тормозил.
Забывают про окружение. На стенде могут стоять разные версии сервисов, и ошибка оказывается несовместимостью контрактов, а не багом в коде.