Что такое метаданные (metadata) в gRPC, для чего они нужны и как с ними работать?

Ответ

Метаданные в gRPC — это набор пар "ключ-значение", которые передаются вместе с RPC-вызовом, но не являются частью бизнес-логики сообщения (Protobuf). Они очень похожи на HTTP-заголовки и служат для передачи служебной информации.

Основные сценарии использования:

  • Аутентификация и авторизация: Передача токенов (JWT, API-ключи) для проверки прав доступа.
  • Трассировка и мониторинг: Передача ID трассировки (trace ID) и ID запроса (request ID) для сквозного отслеживания вызовов в микросервисной архитектуре.
  • Отладка: Передача отладочной информации, например, имени клиента или версии.
  • Управление потоком: Передача информации о сжатии или других параметрах вызова.

Как работать с метаданными в Go:

Метаданные передаются через объект context.Context.

Пример отправки метаданных клиентом:

import "google.golang.org/grpc/metadata"

// 1. Создаем метаданные
md := metadata.Pairs(
    "authorization", "Bearer my-secret-token",
    "request-id", "some-unique-id",
)

// 2. Прикрепляем их к контексту
ctx := metadata.NewOutgoingContext(context.Background(), md)

// 3. Выполняем RPC-вызов с этим контекстом
response, err := client.SomeRPC(ctx, request)

Пример чтения метаданных на сервере:

import "google.golang.org/grpc/metadata"

func (s *server) SomeRPC(ctx context.Context, req *pb.Request) (*pb.Response, error) {
    // 1. Извлекаем метаданные из входящего контекста
    md, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        return nil, status.Errorf(codes.InvalidArgument, "Missing metadata")
    }

    // 2. Читаем значения по ключу (ключи автоматически приводятся к нижнему регистру)
    tokens := md.Get("authorization")
    if len(tokens) > 0 {
        fmt.Println("Auth Token:", tokens[0])
    }

    // ... остальная логика
    return &pb.Response{}, nil
}

Ключевые особенности:

  • Ключи метаданных нечувствительны к регистру и автоматически приводятся к lowercase.
  • Для передачи бинарных данных ключ должен иметь суффикс -bin.
  • Существуют также трейлеры (trailers) — это метаданные, которые сервер отправляет в самом конце обработки запроса, вместе со статусом. Они полезны для передачи информации, которая стала известна только по завершении вызова (например, итоговое время обработки).