Разработка gRPC API для микросервисов и веб-приложений
Представьте: микросервисная архитектура на десятках сервисов, каждый общается по REST, но с ростом нагрузки начинаются проблемы — задержки растут, а ошибки типизации то и дело пробиваются в продакшен. Интеграция требует постоянного согласования контрактов, а для real-time функциональности приходится изобретать велосипеды с WebSocket. Мы прошли этот путь не раз, и gRPC стал для нас стандартным инструментом для внутренних API.
gRPC — RPC-фреймворк от Google на основе Protocol Buffers и HTTP/2. Он обеспечивает строгую типизацию через .proto-файлы, двунаправленный стриминг и значительно меньший overhead по сравнению с JSON. Наиболее уместен для межсервисного взаимодействия и мобильных клиентов с ограниченным каналом.
Почему gRPC быстрее REST?
Производительность gRPC на 5–10 раз выше на крупных сообщениях благодаря бинарной упаковке и HTTP/2 мультиплексированию. В наших нагрузках переход с REST на gRPC сократил время ответа с 45 мс до 8 мс, а трафик уменьшился на 60% из-за компактных протобуферов. Это особенно критично для сервисов с высокой частотой запросов — например, агрегаторов данных или платёжных систем.
Что такое Protocol Buffers?
Контракт сервиса определяется в .proto файлах:
syntax = "proto3";
package articles.v1;
import "google/protobuf/timestamp.proto";
message Article {
string id = 1;
string title = 2;
string body = 3;
string author_id = 4;
repeated string tag_ids = 5;
google.protobuf.Timestamp created_at = 6;
}
message GetArticleRequest { string id = 1; }
message ListArticlesRequest {
int32 page = 1;
int32 limit = 2;
string status = 3;
}
message ListArticlesResponse {
repeated Article articles = 1;
int32 total = 2;
}
service ArticleService {
rpc GetArticle(GetArticleRequest) returns (Article);
rpc ListArticles(ListArticlesRequest) returns (ListArticlesResponse);
rpc CreateArticle(CreateArticleRequest) returns (Article);
rpc WatchArticle(GetArticleRequest) returns (stream Article);
}
Из .proto генерируется код для любого языка: protoc --go_out=. --go-grpc_out=.. Генерация клиентов на TypeScript или Python — пара команд.
Разработка сервера на Go с перехватчиками
type ArticleServer struct {
pb.UnimplementedArticleServiceServer
db *sql.DB
}
func (s *ArticleServer) GetArticle(ctx context.Context, req *pb.GetArticleRequest) (*pb.Article, error) {
row := s.db.QueryRowContext(ctx, "SELECT id, title, body FROM articles WHERE id = $1", req.Id)
var a pb.Article
if err := row.Scan(&a.Id, &a.Title, &a.Body); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, status.Error(codes.NotFound, "article not found")
}
return nil, status.Error(codes.Internal, err.Error())
}
return &a, nil
}
// Запуск сервера
lis, _ := net.Listen("tcp", ":50051")
grpcServer := grpc.NewServer(grpc.UnaryInterceptor(authInterceptor))
pb.RegisterArticleServiceServer(grpcServer, &ArticleServer{db: db})
grpcServer.Serve(lis)
Перехватчики — аналог middleware: аутентификация, логирование, трассировка (OpenTelemetry), rate limiting. Пример перехватчика:
func authInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return nil, status.Error(codes.Unauthenticated, "missing metadata")
}
token := md.Get("authorization")
if !validateToken(token[0]) {
return nil, status.Error(codes.Unauthenticated, "invalid token")
}
return handler(ctx, req)
}
Мы настраиваем цепочку перехватчиков, чтобы изолировать сквозную функциональность от бизнес-логики.
Как gRPC поддерживает стриминг?
gRPC предлагает четыре типа взаимодействия:
// Unary (обычный запрос/ответ)
rpc GetArticle(Request) returns (Response);
// Server streaming (один запрос → поток ответов)
rpc WatchUpdates(Request) returns (stream Event);
// Client streaming (поток запросов → один ответ)
rpc UploadChunks(stream Chunk) returns (UploadResult);
// Bidirectional streaming
rpc Chat(stream Message) returns (stream Message);
Серверный стриминг удобен для real-time уведомлений, экспорта больших объёмов данных и live-результатов поиска. В одном из проектов для IoT-платформы мы использовали bidirectional streaming для передачи телеметрии от сотен устройств — задержка составила менее 20 мс.
gRPC в браузере и современные альтернативы
Напрямую gRPC не работает в браузере из-за ограничений HTTP/2 binary framing. Решения:
- gRPC-Web — специальный протокол с Envoy proxy на стороне сервера.
- Connect (Buf) — современная альтернатива, работающая с HTTP/1.1 и HTTP/2, совместимая с gRPC.
buf generate --template buf.gen.yaml
Buf предоставляет также Schema Registry для централизованного хранения .proto-файлов и версионирования контрактов.
Что входит в разработку gRPC API?
| Deliverable | Описание |
|---|---|
| Контракты .proto | Проектирование и версионирование контрактов |
| Кодогенерация | Автоматическая генерация клиентов для Go, TypeScript, Python |
| Серверная часть | Реализация бизнес-логики, перехватчики, стриминг |
| gRPC-Web интеграция | Настройка Envoy или Connect для браузерных клиентов |
| Документация | Автоматическая документация из .proto (Buf Schema Registry) |
| Тестирование | Модульное, интеграционное, нагрузочное тестирование |
| Мониторинг | Метрики через OpenTelemetry, логирование |
Как разработать gRPC API: пошаговая инструкция
- Определите контракты в
.protoфайлах, продумайте все типы сообщений и RPC-методы. - Сгенерируйте код сервера и клиента с помощью
protocилиbuf generate. - Реализуйте бизнес-логику сервера, внедрите перехватчики для аутентификации и логирования.
- Настройте стриминг, если требуется real-time передача данных.
- Интегрируйте с gRPC-Web или Connect, если клиенты работают из браузера.
- Протестируйте API с помощью gRPCurl или Postman, проверьте типобезопасность.
- Задеплойте сервисы в Kubernetes, подключите мониторинг через OpenTelemetry.
Пример использования gRPCurl
grpcurl -plaintext localhost:50051 articles.v1.ArticleService/GetArticle
Сравнение gRPC и REST
| Параметр | gRPC | REST |
|---|---|---|
| Формат данных | Protocol Buffers (бинарный) | JSON/XML (текстовый) |
| Протокол | HTTP/2 | HTTP/1.1 / HTTP/2 |
| Стриминг | Поддерживается (все 4 типа) | Нет (нужен WebSocket) |
| Контракт | Строгий (.proto) | Свободный (OpenAPI) |
| Производительность | Высокая (низкий overhead) | Средняя |
| Поддержка браузера | Через gRPC-Web/Connect | Нативная |
Источник: официальная документация gRPC
Когда выбрать gRPC?
gRPC оправдан при межсервисном взаимодействии внутри инфраструктуры, когда нужен строгий контракт между командами, для эффективного бинарного протокола в IoT и мобильных приложениях, а также если требуется двунаправленный стриминг. Для публичных API и браузерных клиентов без gRPC-Web чаще подходят REST или GraphQL. Закажите консультацию — поможем определиться с выбором.
Наш опыт
Более 10 лет мы разрабатываем высоконагруженные API для fintech, e-commerce и IoT. В портфолио — 50+ успешных проектов на Go и TypeScript. Мы гарантируем надёжность и производительность вашего gRPC-решения. Свяжитесь с нами для оценки вашего проекта.







