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

Что такое gRPC?

2.3 Middle🔥 151 комментариев
#REST API и HTTP#Архитектура и паттерны

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

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

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

gRPC (Google Remote Procedure Call)

gRPC — это современный фреймворк для удаленного вызова процедур (RPC), разработанный Google. Это альтернатива REST API с акцентом на производительность и простоту использования.

Основные различия от REST

REST (HTTP/1.1):

CLIENT: GET /api/users/123 HTTP/1.1
SERVER: 200 OK
{
  "id": 123,
  "name": "Alice"
}

Данные в JSON/XML, текстовый протокол, один запрос-ответ на соединение.

gRPC (HTTP/2):

CLIENT: Бинарный вызов GetUser(123)
SERVER: Бинарный ответ User{id: 123, name: "Alice"}

Данные в Protocol Buffers (Protobuf), бинарный протокол, мультиплексирование множественных запросов на одном соединении.

Protocol Buffers (Protobuf)

Определение структуры данных и сервиса:

// user.proto
syntax = "proto3";

package user;

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
}

message GetUserRequest {
  int32 user_id = 1;
}

service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc ListUsers (Empty) returns (stream User);
  rpc CreateUser (User) returns (User);
}

Python реализация (grpcio)

Сервер:

import grpc
from concurrent import futures
import user_pb2
import user_pb2_grpc

class UserServicer(user_pb2_grpc.UserServiceServicer):
    def GetUser(self, request, context):
        # Получить пользователя из БД
        user = user_pb2.User(
            id=request.user_id,
            name="Alice",
            email="alice@example.com"
        )
        return user
    
    def ListUsers(self, request, context):
        # Streaming: отправляем множество результатов
        users = [
            user_pb2.User(id=1, name="Alice", email="alice@example.com"),
            user_pb2.User(id=2, name="Bob", email="bob@example.com"),
            user_pb2.User(id=3, name="Charlie", email="charlie@example.com"),
        ]
        for user in users:
            yield user
    
    def CreateUser(self, request, context):
        # Создать пользователя
        request.id = 999  # Установить ID
        return request

# Запустить сервер
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
user_pb2_grpc.add_UserServiceServicer_to_server(
    UserServicer(), server
)
server.add_insecure_port('[::]:50051')
server.start()
print("Server started on port 50051")
server.wait_for_termination()

Клиент:

import grpc
import user_pb2
import user_pb2_grpc

with grpc.insecure_channel('localhost:50051') as channel:
    stub = user_pb2_grpc.UserServiceStub(channel)
    
    # Унарный RPC (один запрос, один ответ)
    request = user_pb2.GetUserRequest(user_id=123)
    user = stub.GetUser(request)
    print(f"User: {user.name} ({user.email})")
    
    # Streaming RPC (один запрос, множество ответов)
    for user in stub.ListUsers(user_pb2.Empty()):
        print(f"User: {user.name}")
    
    # Client streaming (множество запросов, один ответ)
    def create_users():
        for i in range(3):
            yield user_pb2.User(name=f"User{i}", email=f"user{i}@example.com")
    
    # Bidirectional streaming (множество в обе стороны)

Типы RPC в gRPC

1. Unary RPC (один запрос, один ответ):

rpc GetUser (GetUserRequest) returns (User);

2. Server Streaming RPC (один запрос, поток ответов):

rpc ListUsers (Empty) returns (stream User);

3. Client Streaming RPC (поток запросов, один ответ):

rpc CreateUsers (stream User) returns (CreateUsersResponse);

4. Bidirectional Streaming RPC (поток в обе стороны):

rpc Chat (stream Message) returns (stream Message);

Преимущества gRPC

1. Производительность

  • Бинарный формат Protobuf вместо текстового JSON
  • HTTP/2 с мультиплексированием
  • Меньше трафика на сети
  • Быстрее парсинга
REST JSON: {"id": 123, "name": "Alice"}  — 35 байт
gRPC Protobuf: [0x08, 0x7b, 0x12, 0x05, 0x41...]  — 10 байт

2. Строгая типизация Protobuf определяет схему, автоматически генерируется код на разных языках.

3. Streaming Полная поддержка streaming в обе стороны, идеально для реального времени.

4. Поддержка множества языков Автоматическая генерация клиентов и серверов на Python, Java, Go, JavaScript и т.д.

Недостатки gRPC

1. Не человеко-читаем Бинарный формат нельзя посмотреть в браузере или curl:

# Это не работает
curl http://localhost:50051/GetUser

# Нужен специальный grpcurl
grpcurl -plaintext -d '{"user_id": 123}' localhost:50051 user.UserService/GetUser

2. Сложнее отлаживать Требуются специальные инструменты.

3. Требует больше настройки Нужно определить .proto файлы, генерировать код.

Когда использовать gRPC

Микросервисы — высокая производительность ✓ Реальное время — streaming, чаты, уведомления ✓ Высоконагруженные системы — много запросов ✓ Несколько языков — автоматическая генерация на всех ✓ IoT — ограниченная пропускная способность

REST API в браузере — gRPC требует специального клиента ✗ Прототипирование — медленнее чем REST ✗ Простые CRUD операции — overpowered

FastAPI + gRPC (гибридный подход)

from fastapi import FastAPI
import grpc
from concurrent import futures

app = FastAPI()

# REST для браузеров и простых клиентов
@app.get("/api/users/{user_id}")
async def get_user(user_id: int):
    return {"id": user_id, "name": "Alice"}

# gRPC сервер для микросервисов
class UserServicer(user_pb2_grpc.UserServiceServicer):
    def GetUser(self, request, context):
        return user_pb2.User(id=request.user_id, name="Alice")

# Запустить оба сервера
if __name__ == "__main__":
    # gRPC на 50051
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    user_pb2_grpc.add_UserServiceServicer_to_server(UserServicer(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    
    # FastAPI на 8000
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

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