← Назад к вопросам

Какие знаешь виды вызовов у gRPC?

2.0 Middle🔥 201 комментариев
#Сетевые протоколы и API

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Виды вызовов в gRPC

gRPC предлагает четыре основные модели коммуникации между клиентом и сервером, которые позволяют реализовать различные паттерны взаимодействия в распределенных системах. Эти модели основаны на потоковой передаче данных через HTTP/2.

1. Unary RPC (Обычный вызов)

Это самый простой и распространенный тип, аналогичный традиционному запросу-ответу в REST. Клиент отправляет одно сообщение на сервер и получает одно сообщение в ответ.

service UserService {
  rpc GetUser(UserRequest) returns (UserResponse);
}
// Пример реализации на Go
func (s *Server) GetUser(ctx context.Context, req *pb.UserRequest) (*pb.UserResponse, error) {
    user := findUserById(req.Id)
    return &pb.UserResponse{User: user}, nil
}

2. Server Streaming RPC (Серверный поток)

Клиент отправляет одно сообщение, а сервер возвращает поток (sequence) сообщений. Это полезно для передачи больших данных, логов или событий в реальном времени.

service LogService {
  rpc StreamLogs(LogRequest) returns (stream LogMessage);
}
func (s *Server) StreamLogs(req *pb.LogRequest, stream pb.LogService_StreamLogsServer) error {
    logs := fetchLogs(req.Filter)
    for _, log := range logs {
        if err := stream.Send(&pb.LogMessage{Content: log}); err != nil {
            return err
        }
    }
    return nil
}

3. Client Streaming RPC (Клиентский поток)

Клиент отправляет поток сообщений, а сервер возвращает одно сообщение после обработки всех данных. Типичное применение — загрузка файлов или агрегация данных.

service UploadService {
  rpc UploadFile(stream Chunk) returns (UploadStatus);
}
func (s *Server) UploadFile(stream pb.UploadService_UploadFileServer) error {
    var data []byte
    for {
        chunk, err := stream.Recv()
        if err == io.EOF {
            // Клиент завершил отправку
            status := processUpload(data)
            return stream.SendAndClose(&pb.UploadStatus{Ok: true})
        }
        data = append(data, chunk.Content)
    }
}

4. Bidirectional Streaming RPC (Двунаправленный поток)

Клиент и сервер обмениваются потоками сообщений независимо и одновременно. Это наиболее мощная модель, позволяющая реализовать чаты, онлайн-игры или сложные координирующие системы.

service ChatService {
  rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}
func (s *Server) Chat(stream pb.ChatService_ChatServer) error {
    for {
        msg, err := stream.Recv()
        if err == io.EOF {
            return nil
        }
        // Обработка и возможно отправка ответа
        response := processMessage(msg)
        if err := stream.Send(response); err != nil {
            return err
        }
    }
}

Ключевые особенности и выбор модели

  • HTTP/2 как основа: Все виды вызовов используют мультиплексирование и потоковую передачу HTTP/2, что обеспечивает высокую эффективность.
  • Синхронность и асинхронность: В Go реализации часто используют горутины для обработки потоков, особенно в двунаправленном режиме.
  • Контекст (Context): Важно корректно обрабатывать context.Context для управления временем жизни вызовов и распространения метаданных.
  • Обработка ошибок: Каждый вызов должен возвращать error, и для потоковых методов важно отслеживать ошибки при отправке/получении.

Выбор конкретного вида вызова зависит от требований приложения:

  • Unary — для простых запросов (получение пользователя, расчет суммы).
  • Server Streaming — для нотификаций, данных с временными интервалами.
  • Client Streaming — для загрузки данных или постепенной отправки метрик.
  • Bidirectional — для интерактивных и реального времени приложений.

Эти модели делают gRPC мощным инструментом для построения гибких и эффективных микросервисов, позволяя выбирать оптимальный паттерн коммуникации для каждой конкретной задачи.