Как происходит взаимодействие серверов между собой
Что проверяют
Понимаете ли вы, что вызов другого сервиса это сетевой запрос, который может зависнуть, упасть или выполниться дважды. Следом обычно спрашивают, как вы в Go выставляете таймауты и что делаете, если соседний сервис лежит.
Как отвечать
Начните с деления на синхронное и асинхронное взаимодействие:
- HTTP/REST:
net/http, JSON, понятно любой команде и легко отлаживается черезcurl; - gRPC: HTTP/2, контракт в
.proto, сериализация Protocol Buffers, сгенерированный клиент. Есть потоковые вызовы в обе стороны и дедлайны из коробки; - брокер сообщений: Kafka, NATS, RabbitMQ. Отправитель не ждёт получателя, сервисы развязаны по времени, зато появляется вопрос повторной доставки;
- WebSocket: между серверами встречается редко, это скорее канал к клиенту.
Дальше покажите, что знаете про надёжность в Go. У http.Client по умолчанию нет таймаута, поэтому http.Get может ждать ответа бесконечно: создавайте свой клиент с Timeout и передавайте context.WithTimeout в http.NewRequestWithContext. Клиент переиспользуйте, он держит пул соединений, а resp.Body обязательно дочитывайте и закрывайте, иначе соединение не вернётся в пул. В gRPC дедлайн задаётся через контекст и передаётся дальше по цепочке вызовов.
Хорошо дополнить: повторы с экспоненциальной задержкой только для идемпотентных операций, circuit breaker, чтобы не добивать упавший сервис, service discovery через DNS в Kubernetes или Consul, mTLS между сервисами, трассировка через OpenTelemetry.
Где спотыкаются
Перечисляют протоколы и молчат про отказы. Интервьюеру важнее услышать про таймауты, повторы и деградацию, чем про то, что REST использует GET и POST.
Используют дефолтный http.Client или создают новый клиент на каждый запрос. В первом случае зависший сосед копит висящие горутины, во втором теряется пул соединений.
Говорят «gRPC всегда быстрее REST». Выигрыш заметен на частых мелких вызовах и больших объёмах, но gRPC сложнее отлаживать, а из браузера напрямую он не работает без прослойки вроде gRPC-Web.