REST против RPC: разница в мышлении
Урок противопоставляет два способа мышления об API: «вызвать действие» (RPC) и «работать с вещами» (REST), и показывает, когда какой уместен.
RPC (Remote Procedure Call) — стиль API, где эндпоинты называются глаголами-действиями (
getUser,createOrder); REST — стиль, где эндпоинты называются существительными-ресурсами, а действие задаёт HTTP-метод.
Разница между REST и RPC — не в технологии, а в образе мышления. RPC спрашивает: «какие действия я хочу вызвать на сервере?» REST спрашивает: «какие сущности есть в системе и что я с ними делаю?» Один и тот же продукт можно спроектировать в обоих стилях, и выбор задаёт всю структуру API.
RPC: действия как эндпоинты
В RPC-мышлении сервер — это набор удалённых функций. Вы «вызываете процедуру» по сети так же, как вызвали бы локальную функцию. Каждое действие — отдельный эндпоинт-глагол:
POST /getUser
POST /createUser
POST /deleteUser
POST /activateUser
POST /resetUserPassword
Имя эндпоинта — это имя действия. Обычно всё идёт через POST, а параметры передаются в теле. Структура API повторяет список функций сервера: сколько действий — столько адресов. Это интуитивно для тех, кто привык мыслить функциями.
REST: ресурсы и единый набор глаголов
В REST-мышлении вы сначала выделяете сущности (ресурсы), а действия выражаете небольшим стандартным набором HTTP-методов. Те же операции выглядят так:
GET /users/1 получить пользователя
POST /users создать пользователя
DELETE /users/1 удалить пользователя
Сравним лоб в лоб классический пример:
| Задача | RPC-стиль | REST-стиль |
| получить пользователя | POST /getUser | GET /users/1 |
| создать пользователя | POST /createUser | POST /users |
| удалить пользователя | POST /deleteUser | DELETE /users/1 |
| список заказов юзера | POST /getUserOrders | GET /users/1/orders |
В REST «глаголы» фиксированы (их горстка) и переиспользуются для всех ресурсов. В RPC каждый новый сценарий рождает новый глагол-эндпоинт. Отсюда главное практическое различие: REST-API растёт «вширь» по ресурсам, RPC-API — «вглубь» по действиям.
Плюсы и минусы каждого подхода
| Критерий | REST | RPC |
| Предсказуемость | высокая: зная ресурс, угадываешь операции | низкая: каждый глагол надо знать заранее |
| Кэширование | лёгкое (GET кэшируется из коробки) | трудное (всё POST) |
| Сложные действия | иногда натянуто (что такое ресурс «отправить письмо»?) | естественно: sendEmail |
| Связность | слабая, легко эволюционировать | API повторяет внутренние функции |
У REST есть честная слабость: не всё в мире — «вещь». Действие «пересчитать корзину» или «отправить письмо» — это операция, а не ресурс, и втискивать его в существительное бывает неуклюже. В таких случаях даже RESTful API иногда добавляет «действие-ресурс» вроде POST /carts/1/recalculate — прагматичный компромисс.
Когда RPC уместен
RPC — не «устаревший плохой REST», а отдельный инструмент со своей нишей:
- API, ориентированный на действия, а не на данные. Если сервис — это набор команд (
recalculate,render,translate), ресурсная модель только мешает. - Внутренние сервисы (microservices). Между своими сервисами, где не нужны браузерное кэширование и публичная предсказуемость, скорость и строгий контракт важнее.
- Высокая нагрузка и низкая задержка. Бинарные RPC-протоколы быстрее текстового JSON-over-HTTP.
gRPC — современный взгляд на RPC
Самый известный сегодня RPC-фреймворк — gRPC от Google. Вы описываете сервис и его методы в файле .proto, а инструмент генерирует клиент и сервер для многих языков. Данные передаются в компактном бинарном формате Protocol Buffers поверх HTTP/2 — это быстрее и легче, чем JSON.
service UserService {
rpc GetUser (GetUserRequest) returns (User);
rpc CreateUser (CreateUserRequest) returns (User);
}
Это чистое RPC-мышление: вы объявляете методы (GetUser, CreateUser), а не ресурсы. gRPC силён во внутренней связи микросервисов: строгий типизированный контракт, высокая производительность, стриминг. Слабее — там, где нужен публичный API для браузеров и простая отладка через curl: gRPC бинарный и не читается глазами. Многие системы используют оба подхода: REST наружу, gRPC внутри.
Как работает под капотом
Почему один и тот же продукт даёт такие разные API? Потому что отличается вопрос проектировщика. Проследим мышление на примере «интернет-магазин»:
RPC-мышление: "какие операции нужны?"
--> getProduct, addToCart, checkout, payOrder ...
--> каждая = новый эндпоинт-глагол
REST-мышление: "какие сущности есть?"
--> products, carts, orders, payments
--> над каждой = GET/POST/PUT/DELETE
RPC отражает код сервера (его функции), REST отражает предметную область (её сущности). Поэтому REST-API обычно стабильнее: сущности «товар» и «заказ» меняются реже, чем список функций. Зато RPC точнее ложится на действия и часто короче для команд-операций.
Практический вывод для курса: мы проектируем ресурсный REST-стиль уровня 2 — он предсказуем, кэшируем и отлично подходит для публичных веб-API. Но держим в голове, что RPC (особенно gRPC) — законный выбор для внутренних высоконагруженных и action-ориентированных сервисов.
Частые ошибки
- Городить глаголы в URL и звать это REST.
POST /getUserилиGET /users/getById?id=1— это RPC внутри REST-обёртки. В REST действие — это метод, а не часть пути. - Считать RPC «плохим» по определению. Для внутренних сервисов и action-API RPC/gRPC часто удобнее и быстрее REST.
- Втискивать любое действие в ресурс силой. Иногда честнее добавить action-эндпоинт (
POST /orders/7/cancel), чем выдумывать искусственный ресурс. - Путать gRPC и REST по транспорту. gRPC бинарный (Protocol Buffers, HTTP/2), REST обычно текстовый (JSON, HTTP/1.1) — это влияет на отладку и кэширование.
Итог
- REST и RPC — разные способы мышления: «работаю с вещами» против «вызываю действия».
- RPC: эндпоинты-глаголы (
/getUser), обычно POST; REST: ресурсы-существительные (GET /users/1) с фиксированным набором методов. - REST предсказуем и кэшируем; RPC естественнее для действий и быстрее в бинарных вариантах.
- gRPC — современный RPC: бинарный, типизированный, силён внутри микросервисов.
- Часто оба сочетают: REST наружу, gRPC внутри. В курсе проектируем ресурсный REST уровня 2.