Гайды
gRPC: основы и пример на Python и Go
Protobuf, кодоген, unary и streaming, mTLS и metadata, ошибки и когда выбирать gRPC вместо REST.
~11 мин чтения
gRPC: основы и пример на Python и Go
gRPC — RPC поверх HTTP/2 с Protobuf как контрактом: строгие типы, потоковые вызовы (client/server/bidi streaming), кодоген из .proto. Альтернатива JSON REST для внутренних сервисов. Сравнение стилей API — GraphQL vs REST; OpenAPI — спецификация и генерация клиентов.
1. IDL: пример service.proto
syntax = "proto3";
package demo.v1;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest { string name = 1; }
message HelloReply { string message = 1; }
Генерация:
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. service.proto
2. Python: сервер (скелет)
from concurrent import futures
import grpc
import service_pb2
import service_pb2_grpc
class Greeter(service_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return service_pb2.HelloReply(message=f"Hello, {request.name}")
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
service_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port("[::]:50051")
server.start()
server.wait_for_termination()
Клиент: stub + channel (grpc.insecure_channel("localhost:50051")).
Дедлайны: на клиенте оборачивайте контекст в context.WithTimeout; на сервере проверяйте context.Err() в длинных циклах. Без этого отменённые клиенты продолжают грузить CPU.
Отладка без кода клиента: grpcurl вызывает методы по имени, если включён server reflection (в проде reflection часто отключают).
3. Go: сервер (идея)
protoc с --go_out и --go-grpc_out; реализация интерфейса, grpc.NewServer(), RegisterGreeterServer.
4. Streaming
- Unary — один запрос, один ответ.
- Server streaming — один запрос, поток ответов (логи, прогресс).
- Client streaming — загрузка чанками.
- Bidi — чат, прокси-потоки.
5. mTLS и metadata
Для продакшена — TLS на канале, часто взаимная TLS между сервисами. Metadata в gRPC — аналог заголовков HTTP для трейсинга (grpc-trace-bin), JWT и т.д.
6. Ошибки и коды
context.set_code(grpc.StatusCode.NOT_FOUND) + set_details. Клиент различает сетевые сбои и бизнес-ошибки.
7. Keepalive и лимиты сообщений
На долгоживущих каналах задайте keepalive, чтобы прокси и балансировщики не рвали «тихие» соединения; ограничьте размер кадра, чтобы один крупный запрос не выбил память.
opts = [
("grpc.keepalive_time_ms", 10_000),
("grpc.keepalive_timeout_ms", 5_000),
("grpc.max_send_message_length", 8 * 1024 * 1024),
("grpc.max_receive_message_length", 8 * 1024 * 1024),
]
ch = grpc.insecure_channel("svc:50051", options=opts)
В Go — grpc.WithDefaultCallOptions, grpc.KeepaliveParams на grpc.NewClient / dial options (см. документацию вашей версии google.golang.org/grpc).
8. Когда gRPC уместен
- Внутренняя микросервисная сеть, низкая латентность, контракт важнее человекочитаемого JSON в браузере.
- Для публичного браузерного API чаще REST/GraphQL (gRPC-web — отдельная история).
9. Чек-лист
- Версия в package или в имени сервиса (
GreeterV2). - Keepalive и лимиты размера сообщения на клиенте и сервере.
- Таймауты на канале и deadline в RPC.
- Совместимость
proto3optional / JSON mapping по гайду команды. - Регенерация stubs в CI при изменении
.proto.
Дальше: тег gRPC