10 вопросов
gRPC - RPC-фреймворк на базе HTTP/2 и Protocol Buffers. Сервисы описываются в .proto файлах; генерируется код клиента и сервера. Типизация, потоковая передача (streaming), кросс-язычность. В Go: protoc с плагином go и go-grpc; сгенерированные типы и интерфейсы. Подходит для микросервисов и внутренних API.
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
// protoc --go_out=. --go-grpc_out=. ./*.protoProtobuf - формат сериализации и язык описания (.proto): сообщения с полями и типами, сервисы с RPC-методами. Компилятор protoc генерирует код (структуры, сериализация). Бинарный формат компактнее JSON, схема обязательна. В Go получают структуры с полями и методами Marshal/Unmarshal; для gRPC - интерфейсы сервера и клиентские вызовы.
message User {
int64 id = 1;
string name = 2;
}gRPC: бинарный протокол, типизация, потоковая передача, один HTTP/2 connection, эффективность. REST: JSON, браузеры, кеширование, простота отладки. gRPC выбирают для внутренних сервисов (Go-to-Go, микросервисы), стриминга, высокой нагрузки. REST - для публичных API и веб-клиентов. В Go gRPC интегрируется естественно (сгенерированный код, контекст, ошибки).
Unary: один запрос - один ответ. Server stream: один запрос - поток ответов (stream Reply). Client stream: поток запросов - один ответ. Bidirectional: поток запросов и ответов. В Go сервер реализует интерфейс с методами (Send/Recv для stream); клиент вызывает метод и итерирует по потоку. Удобно для логов, телеметрии, чатов.
rpc StreamLogs (StreamRequest) returns (stream LogEntry);
rpc Chat (stream Message) returns (stream Message);Интерцептор - middleware для вызовов: аутентификация, логирование, метрики, трейсинг. В Go: UnaryInterceptor и StreamInterceptor при создании сервера; цепочка оборачивает handler. На клиенте - UnaryInterceptor и StreamInterceptor при создании соединения. В интерцепторе вызывают handler(ctx, req) или stream-обертку и могут менять контекст (например, добавить user id после auth).
s := grpc.NewServer(
grpc.UnaryInterceptor(authInterceptor),
grpc.StreamInterceptor(logStreamInterceptor),
)В .proto задают package (или option go_package для Go), message с полями и номерами, service с rpc методами (входной и выходной тип). Для Go генерируют: .pb.go с сообщениями и .pb.grpc.go с интерфейсом сервера и клиентским кодом. Сервер реализует сгенерированный интерфейс и регистрирует его в grpc.Server.
syntax = "proto3";
option go_package = "pkg/proto";
service UserService {
rpc GetUser (GetUserRequest) returns (User);
}
message GetUserRequest { int64 id = 1; }
message User { int64 id = 1; string name = 2; }Устанавливают protoc и плагины: protoc-gen-go, protoc-gen-go-grpc. Команда: protoc --go_out=. --go-grpc_out=. --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative *.proto. В проекте часто делают go generate с этой командой или Makefile. Сгенерированные файлы коммитят или генерируют в CI. Буферы и зависимости: google.golang.org/protobuf, google.golang.org/grpc.
//go:generate protoc --go_out=. --go-grpc_out=. ./*.protoДедлайн передается через context: context.WithTimeout(ctx, 5*time.Second); этот context передают в вызов. Сервер проверяет context.Deadline() и может прервать работу. При истечении клиент получает ошибку codes.DeadlineExceeded. В Go на клиенте всегда задают дедлайн; на сервере пробрасывают context в бизнес-логику и проверяют при долгих операциях.
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
resp, err := client.GetUser(ctx, &pb.GetUserRequest{Id: 1})Ошибки передаются как status (код + сообщение). Коды: OK, InvalidArgument, NotFound, Unavailable, DeadlineExceeded и др. В Go на сервере возвращают status.Error(codes.NotFound, "user not found") или status.Errorf. На клиенте проверяют: st, ok := status.FromError(err); if ok { st.Code(), st.Message() }. Детали в Any (grpc/details) для расширенной информации.
return nil, status.Errorf(codes.NotFound, "user %d not found", id)
if st, ok := status.FromError(err); ok && st.Code() == codes.NotFound { ... }Reflection позволяет клиентам узнавать сервисы и методы в runtime (без статического .proto). Удобно для отладки (grpcurl, BloomRPC) и динамических клиентов. В Go подключают: import _ "google.golang.org/grpc/reflection"; reflection.Register(grpcServer). В продакшене часто отключают из соображений безопасности.
import _ "google.golang.org/grpc/reflection"
reflection.Register(s)