Розробка 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-рішення. Зв'яжіться з нами для оцінки вашого проєкту.







