Какие подходы для синхронного межсервисного взаимодействия в Go вы использовали? Расскажите о плюсах и минусах.

Ответ

Для синхронного взаимодействия между сервисами в Go я использовал два основных подхода: HTTP/REST и gRPC.

1. HTTP/REST

Основан на стандартном протоколе HTTP. Легко отлаживать, широко распространен и понятен большинству разработчиков. В Go реализуется с помощью стандартной библиотеки net/http.

Пример клиента:

import (
    "net/http"
    "io"
    "log"
)

func fetchData() {
    resp, err := http.Get("https://api.example.com/data")
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    // ... обработка body
}
  • Плюсы: Простота, человекочитаемый формат (JSON), огромная экосистема инструментов (Postman, curl).
  • Минусы: Относительно медленная сериализация/десериализация JSON, избыточность текстового протокола.

2. gRPC

Высокопроизводительный RPC-фреймворк от Google. Использует Protocol Buffers для сериализации данных и HTTP/2 для транспорта.

Пример клиента:

import (
    "google.golang.org/grpc"
    "log"
)

func callService() {
    conn, err := grpc.Dial("server-address:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    client := pb.NewMyServiceClient(conn)
    response, err := client.GetData(context.Background(), &pb.Request{...})
    // ... обработка response
}
  • Плюсы: Высокая производительность, строгая типизация контрактов (.proto файлы), автоматическая кодогенерация клиентов и серверов, поддержка стриминга.
  • Минусы: Бинарный формат сложнее отлаживать, требует предварительной компиляции .proto файлов.

Ключевые аспекты при реализации:

Независимо от выбора, важно учитывать:

  • Таймауты: Всегда использовать context.WithTimeout для предотвращения "зависших" запросов.
  • Повторные запросы (Retry): Реализация логики повторных попыток с экспоненциальной задержкой (exponential backoff) для обработки временных сбоев сети.
  • Отказоустойчивость: Использование паттерна Circuit Breaker для предотвращения каскадных сбоев.
  • Балансировка нагрузки: Настройка клиентской или серверной балансировки нагрузки.

Вывод: REST отлично подходит для публичных API, а gRPC — для высокопроизводительного внутреннего взаимодействия между микросервисами.