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 /getUserGET /users/1
создать пользователяPOST /createUserPOST /users
удалить пользователяPOST /deleteUserDELETE /users/1
список заказов юзераPOST /getUserOrdersGET /users/1/orders

В REST «глаголы» фиксированы (их горстка) и переиспользуются для всех ресурсов. В RPC каждый новый сценарий рождает новый глагол-эндпоинт. Отсюда главное практическое различие: REST-API растёт «вширь» по ресурсам, RPC-API — «вглубь» по действиям.

Плюсы и минусы каждого подхода

КритерийRESTRPC
Предсказуемостьвысокая: зная ресурс, угадываешь операциинизкая: каждый глагол надо знать заранее
Кэшированиелёгкое (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.
Проверьте себя
1. Как в REST-стиле выглядит получение пользователя с id=1 по сравнению с RPC?
AREST: POST /getUser; RPC: GET /users/1
BREST: GET /users/1; RPC: POST /getUser
CОба используют POST /getUser
DОба используют GET /users/1
2. В чём ключевая разница в мышлении между REST и RPC?
AREST быстрее RPC во всех случаях
BRPC мыслит ресурсами-сущностями, а REST — действиями
CREST мыслит сущностями (вещами), а RPC — действиями (вызовами функций)
DРазница только в формате данных, а не в структуре API
3. Когда RPC (например gRPC) обычно уместнее REST?
AДля публичного API, который отлаживают через curl в браузере
BДля внутренних высоконагруженных микросервисов с action-ориентированным контрактом
CКогда нужно лёгкое кэширование GET-ответов
DКогда важна предсказуемость URL для сторонних разработчиков