Взаимодействие сервисов: REST и gRPC
Соединяйте сервисы синхронно и эффективно
«Взаимодействие сервисов: REST и gRPC» — бесплатный урок PHP Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения PHP Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс PHP Academy содержит 4 уроков всего.
REST и gRPC
Сервисам нужно взаимодействовать синхронно: отправляется запрос, возвращается ответ. Два основных варианта — REST поверх HTTP/JSON и gRPC поверх HTTP/2 + буферов протокола. Они оптимизированы для разных задач: REST — для доступности и понятности, gRPC — для скорости и строгих контрактов.
В этом уроке показаны оба подхода с точки зрения PHP и объясняется, когда выбирать каждый из них.
REST: универсальный язык
REST представляет ресурсы через URL и использует методы HTTP и коды состояния для передачи смысла. Его сильные стороны — универсальные инструменты, возможность кэширования, удобная отладка с помощью curl и отсутствие необходимости в специальном клиенте. Слабые стороны — многословный JSON, отсутствие принудительной схемы и ограничение моделью «запрос–ответ».
Для общедоступных API и конечных точек, предназначенных для браузеров, REST почти всегда является правильным выбором.
Вызов REST-сервиса
Используйте HTTP-клиент PSR-18 (здесь — Guzzle). Всегда задавайте тайм-аут подключения и запроса: неограниченный вызов медленного узла может исчерпать рабочие процессы PHP-FPM и вызвать каскадный сбой.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$http = new Client([
'base_uri' => 'http://customers-svc/',
'connect_timeout' => 1.0, // never block forever on connect
'timeout' => 3.0, // total request budget
'http_errors' => false,
]);
$res = $http->get('customers/42', ['headers' => ['Accept' => 'application/json']]);
if ($res->getStatusCode() === 200) {
$customer = json_decode((string) $res->getBody(), true);
echo $customer['email'] . "\n";
}Коды состояния — это контракт
В межсервисном REST коды состояния HTTP и есть Ваш протокол ошибок. Обращайтесь с ними осознанно:
2xx— успех;4xx— ошибка вызывающей стороны (не повторяйте запрос вслепую);5xxи тайм-ауты допускают повторную попытку.- Используйте
409для конфликтов,422для ошибок проверки,429для ограничений частоты запросов (учитывайтеRetry-After).
Повторный запрос к 400 лишь тратит ресурсы; повторный запрос к 503 с увеличивающейся задержкой — правильный подход.
<?php
function isRetryable(int $status): bool {
return $status === 0 // timeout/connection error
|| $status === 429
|| ($status >= 500 && $status !== 501);
}
var_dump(isRetryable(503)); // true
var_dump(isRetryable(400)); // falsegRPC: сначала контракт, затем скорость
gRPC использует буферы протокола: Вы определяете сервисы и сообщения в файле .proto, а затем генерируете строго типизированные клиентские и серверные заглушки. Благодаря HTTP/2 и двоичному представлению в буферах протокола такой обмен намного компактнее и быстрее, чем JSON, а также поддерживает потоковую передачу.
syntax = "proto3";
package customers;
service Customers {
rpc GetCustomer (GetCustomerRequest) returns (Customer);
}
message GetCustomerRequest { string id = 1; }
message Customer {
string id = 1;
string email = 2;
int32 loyalty_points = 3;
}Генерация заглушек PHP
Установите расширение gRPC для PHP и плагин protoc, затем сгенерируйте классы клиентов из файла .proto. PHP может выступать полнофункциональным клиентом gRPC через ext-grpc; для запуска нативного сервера gRPC на PHP обычно требуются Roadrunner или Swoole.
pecl install grpc
composer require grpc/grpc google/protobuf
protoc --proto_path=. \
--php_out=./generated \
--grpc_out=./generated \
--plugin=protoc-gen-grpc=$(which grpc_php_plugin) \
customers.protoВызов клиента gRPC
Сгенерированные заглушки предоставляют типизированные запросы и ответы. Вызов gRPC возвращает сообщение и объект status — всегда проверяйте код состояния, прежде чем доверять ответу.
<?php
require 'vendor/autoload.php';
use Customers\CustomersClient;
use Customers\GetCustomerRequest;
use Grpc\ChannelCredentials;
$client = new CustomersClient('customers-svc:50051', [
'credentials' => ChannelCredentials::createInsecure(),
]);
$req = (new GetCustomerRequest())->setId('42');
[$reply, $status] = $client->GetCustomer($req)->wait();
if ($status->code === \Grpc\STATUS_OK) {
echo $reply->getEmail(), "\n";
} else {
fwrite(STDERR, "gRPC error: {$status->details}\n");
}Эволюция схемы
Буферы протокола рассчитаны на прямую и обратную совместимость, если соблюдать их правила:
- Никогда не переиспользуйте и не изменяйте номер поля. Добавляйте новые поля с новыми номерами.
- Помечайте удалённые поля как
reserved, чтобы их номер нельзя было использовать повторно. - Старые клиенты игнорируют неизвестные поля; для отсутствующих полей используются значения по умолчанию их типов.
JSON/REST не даёт ничего из этого бесплатно — совместимость приходится обеспечивать по соглашению (и в идеале — общей схемой OpenAPI с контрактными тестами).
message Customer {
string id = 1;
string email = 2;
reserved 3; // old 'loyalty_points', never reuse 3
reserved "loyalty_points";
string display_name = 4; // new field, safe additive change
}Потоковая передача
gRPC поддерживает четыре типа вызовов; REST изначально поддерживает только первый:
- Унарный — один запрос, один ответ.
- Потоковая передача от сервера — один запрос, поток ответов (например, обновления в реальном времени).
- Потоковая передача от клиента — поток запросов, один ответ (например, массовая загрузка).
- Двунаправленная передача — оба потока идут одновременно.
Если Ваш сценарий предполагает передачу данных по инициативе сервера или длительный поток данных, потоковая передача gRPC эффективнее опроса конечной точки REST.
Передача контекста и предельных сроков
Синхронные вызовы образуют цепочки, поэтому с каждым запросом должны передаваться две вещи: идентификатор корреляции и трассировки для сквозного отслеживания и предельный срок, чтобы медленный конечный узел не заставил зависнуть всю цепочку. В gRPC предусмотрены предельные сроки; в REST их имитируют с помощью уменьшающегося бюджета времени ожидания, передаваемого дальше по цепочке.
<?php
// REST: shrink the remaining budget as the call chain deepens
function forwardHeaders(array $incoming, float $remainingMs): array {
return [
'X-Correlation-Id' => $incoming['X-Correlation-Id'] ?? bin2hex(random_bytes(8)),
// downstream must finish within what's left of our budget
'X-Timeout-Ms' => (string) max(0, (int) $remainingMs),
];
}
print_r(forwardHeaders(['X-Correlation-Id' => 'trace-9'], 1500));Как выбрать между ними
Практическое руководство по выбору:
- REST — для общедоступных и партнёрских API, браузерных клиентов, простых операций CRUD, удобной отладки и широкой поддержки кэширования.
- gRPC — для внутренних межсервисных вызовов с большим объёмом трафика и малой задержкой, строгих типизированных контрактов и потоковой передачи.
Многие системы используют оба варианта: gRPC за шлюзом между сервисами, REST на внешнем уровне для окружающего мира. Не заставляйте один инструмент выполнять работу другого.
Быстрая проверка
Как подобрать протокол для конкретного сценария.
Итоги
Синхронное взаимодействие сервисов:
- REST/JSON — универсальный, удобный для отладки и поддерживающий кэширование; коды состояния являются контрактом; всегда задавайте тайм-ауты.
- gRPC/буферы протокола — сначала контракт, компактность, скорость и потоковая передача; генерируйте типизированные заглушки PHP.
- Определяйте возможность повторной попытки по кодам состояния и gRPC; никогда не повторяйте запросы с ошибками клиента.
- Развивайте схемы аддитивно — никогда не переиспользуйте номера полей буферов протокола.
- REST на внешнем уровне, а gRPC между внутренними сервисами — распространённое и разумное разделение.
Далее: маршрутизация и поиск всех этих сервисов с помощью шлюзов и механизмов обнаружения.
Изучай PHP с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 49
- Уроки
- 195
Часто задаваемые вопросы
Урок «Взаимодействие сервисов: REST и gRPC» бесплатный?
Да — полный текст урока «Взаимодействие сервисов: REST и gRPC» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс PHP Academy, подпишись на CoddyKit PRO. Курс PHP Academy содержит 4 уроков всего.
Чему я научусь в уроке «Взаимодействие сервисов: REST и gRPC»?
Соединяйте сервисы синхронно и эффективно Ты практикуешь PHP Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать PHP Academy?
Предыдущий опыт не требуется. PHP Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Взаимодействие сервисов: REST и gRPC»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке PHP Academy?
Да. Каждый урок PHP Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- От монолита к микросервисам
- Взаимодействие сервисов: REST и gRPC
- Шлюзы API и обнаружение сервисов
- Отказоустойчивость: размыкатели и повторные попытки