gRPC - фреймворк віддалених викликів процедур: клієнт викликає метод на сервері так, ніби це локальна функція. Контракт описується у файлі .proto мовою Protocol Buffers:
syntax = "proto3";
package billing.v1;
service InvoiceService {
rpc GetInvoice (GetInvoiceRequest) returns (Invoice);
rpc StreamPayments (StreamPaymentsRequest) returns (stream Payment);
}
message GetInvoiceRequest {
int64 id = 1;
}
message Invoice {
int64 id = 1;
string number = 2;
int64 total_cents = 3;
repeated LineItem items = 4;
}
З .proto генеруються клієнти й серверні заготовки для десятків мов - контракт однаковий для Go, Java, PHP, Node.js.
Чому його обирають для внутрішнього зв'язку сервісів:
- компактність і швидкість: Protocol Buffers - бінарний формат, повідомлення в рази менші за JSON і швидше розбираються. Імена полів не передаються - лише номери;
- HTTP/2: одне з'єднання для багатьох паралельних викликів, стиснення заголовків;
- стримінг: від сервера, від клієнта і двобічний - потоки подій, великі вивантаження без пагінації;
- суворий контракт: типи перевіряються при генерації коду, а не в рантаймі;
- дедлайни й скасування вбудовані в протокол: клієнт задає, скільки готовий чекати, і скасування поширюється ланцюжком викликів.
Обмеження:
- браузер не говорить gRPC напряму - потрібен gRPC-Web з проксі (Envoy) чи шлюз, що перетворює на REST/JSON;
- налагодження: бінарні повідомлення не прочитаєш у DevTools - потрібні
grpcurl, Postman з підтримкою gRPC; - PHP-FPM погано підходить для gRPC-сервера (довгі з'єднання, HTTP/2) - сервери пишуть на Go, Java, Node.js, а з PHP частіше виступають клієнтом (розширення
grpc) або використовують RoadRunner; - інфраструктура: балансувальники мають розуміти HTTP/2 і довгоживучі з'єднання.
Відповіді й помилки: у gRPC власні коди стану (NOT_FOUND, UNAVAILABLE, DEADLINE_EXCEEDED, PERMISSION_DENIED) замість HTTP-кодів.
Типова картина: публічне API - REST/JSON, внутрішні виклики між сервісами - gRPC, асинхронні події - черги чи брокери повідомлень.