Как дебажить сетевые проблемы при взаимодействии сервисов
Что проверяют
Есть ли у вас система: идёте ли вы по уровням от DNS до приложения или сразу хватаетесь за tcpdump. Вопрос поведенческий, так что следом почти наверняка попросят реальный случай: что сломалось, как нашли, что поменяли.
Как отвечать
Сначала определите уровень, текст ошибки Go уже подсказывает: no such host это DNS, connection refused значит порт никто не слушает, i/o timeout при подключении указывает на firewall или сетевую политику, context deadline exceeded на то, что ответ не уложился в ваш дедлайн. Дальше по слоям:
- DNS и порт:
digиnc -vz host portиз того же пода. В Kubernetes удобно подключить отладочный контейнер черезkubectl debug; - HTTP и TLS:
curl -vс-wи полямиtime_namelookup,time_connect,time_appconnect,time_starttransferпоказывает, где уходит время. TLS отдельно проверяетсяopenssl s_client; - изнутри Go:
net/http/httptraceс хукамиDNSDone,ConnectDone,GotConn(там видно, переиспользовано ли соединение) иTLSHandshakeDone. Для gRPC логи транспорта включаютGRPC_GO_LOG_SEVERITY_LEVEL=infoиGRPC_GO_LOG_VERBOSITY_LEVEL=99; - сокеты: в
ss -tanpтысячиTIME_WAITговорят, что соединения не переиспользуются, а висящиеCLOSE_WAIT, что ваш код их не закрывает; - трафик:
tcpdump -i any port 8080 -w dump.pcapи разбор в Wireshark, когда гипотеза уже есть; - трейсы: OpenTelemetry показывает, на каком переходе между сервисами копится задержка.
Историю из опыта стройте так же: симптом, гипотеза, чем проверили, причина, исправление и что добавили в мониторинг. Если такого случая не было, честно скажите и разберите по этим шагам учебную ситуацию.
Где спотыкаются
Проверяют связь через ping. ICMP часто закрыт, а ответ на него ничего не говорит о нужном TCP-порте.
Не знают умолчаний клиента: у http.DefaultClient нет таймаута, а DefaultMaxIdleConnsPerHost равен 2, и под нагрузкой сервис открывает новые соединения вместо старых.
Не вычитывают и не закрывают resp.Body. Соединение не возвращается в пул, отсюда утечка горутин и те самые CLOSE_WAIT.