gRPC или REST — вопрос не про моду
На сеньорском собесе этот вопрос редко звучит как "что лучше". Обычно формулировка другая: "у вас внутренний сервис дергает другой сервис тысячи раз в секунду, что выберете и почему".
REST поверх HTTP/1.1 с JSON — текстовый протокол, схема не зафиксирована жёстко, каждый запрос — отдельное соединение или keep-alive, но без мультиплексирования на уровне семантики запроса. gRPC работает поверх HTTP/2, сериализует Protobuf в бинарный формат, схема описана в .proto и генерирует клиент и сервер на разных языках из одного контракта.
Разница на практике не в "быстрее/медленнее абстрактно", а в конкретных вещах. Protobuf компактнее JSON при той же нагрузке — меньше трафика и меньше CPU на сериализацию. HTTP/2 даёт мультиплексирование нескольких запросов в одном TCP-соединении, поэтому много мелких RPC не упираются в лимит соединений. Обратная сторона — gRPC неудобен для браузерного клиента напрямую (нужен grpc-web или прокси) и хуже дебажится руками: не curl'нёшь и не прочитаешь глазами.
// REST: контракт в голове и в Swagger @GetMapping("/orders/{id}") OrderDto getOrder(@PathVariable Long id);
// gRPC: контракт в .proto, код сгенерирован service OrderService { rpc GetOrder (OrderRequest) returns (OrderResponse); }
Следом почти всегда спрашивают: а что с versioning? В REST версия обычно в URL или в заголовке, и обратная совместимость — вопрос дисциплины команды. В Protobuf обратная совместимость встроена в формат: можно добавлять новые поля с новыми номерами, не ломая старых клиентов, но нельзя переиспользовать номер поля после удаления — это ловушка, в которую попадают почти все, кто думает, что protobuf сам всё разрулит.
Выбор между ними — это выбор между человекочитаемостью и производительностью с строгой схемой. Для внешнего публичного API почти всегда REST, для внутреннего межсервисного трафика с высокой частотой — gRPC.
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки