
Картина мира: почему браузер — главный блокер для «настоящего» gRPC
Если коротко, gRPC живёт поверх HTTP/2 и активно полагается на стримы. А в браузере до сих пор нет низкоуровневого API, который позволил бы JavaScript управлять HTTP/2‑стримами на том уровне, который нужен gRPC. Даже unary‑вызов в gRPC — это частный случай стрима: открыли поток, отдали запрос, забрали ответ, закрылись. Пока браузеры не дадут этот «рычаг», все WEB‑решения — это компромиссы разной степени изящности.
Чем это оборачивается на практике:
Нативные bidi‑стримы из браузера недоступны
Приходится конвертировать транспорт: HTTP/1.1 или WebSocket → что‑то «похоже на gRPC» → gRPC/HTTP2 на бэкенде
Добавляются прокси, адаптеры и слой совместимости, где теряется часть достоинств «чистого» gRPC
Ах, да, меня зовут Эдгар Сипки, я все также евангелист gRPC && OpenSource :) Кстати, мой канал, там я гораздо чаще пишу (а скоро еще и начну снимать очень много крутого контента про gRPC и Go)
Попытка №2: gRPC‑Web от Google — официально, но провально странно

Ну что же, второй раунд начат, еще и самим Google и в итоге в 2016 году зарелизили gRPC-Web.
То есть, поддержка от компании, чуть ли не локомотива всей web индустрии и параллельно с этим БУКВАЛЬНО основателя gRPC. Что могло пойти не так?
А вот что:

Но как тогда он должен работать? А тут на самом деле все очень просто, gRPC‑Web — это генерация JS/TS‑клиента плюс reverse‑proxy (часто Envoy), который переводит запросы из браузера HTTP/1.1 в HTTP/2 к вашему gRPC‑серверу, то есть все это работает через “конвертацию” как адаптер. Как gRPC-Gateway, но наоборот, только в этом случае приходится еще и убеждать фронтендеров начать работать с нестандартной для них технологией.

Но, в итоге это опять таки не полноценный gRPC, но помимо этого, зайдя в документацию, вы практически сразу увидите прекрасный сюрприз :-)
Client-streaming and half-duplex streaming
We don't plan to support client-streaming via Fetch/upload-streams (See Appendix on backgrounds on the Chrome Origin Trial). As a result, half-duplex bidi streaming won't be supported via Fetch/streams either.
Client-streaming and half-duplex bidi streaming will be addressed when Full-duplex streaming is supported via WebTransport (see below).

Вот эти ребята в 2016 году, соответственно, решили сделать второй раунд. Они запустили gRPC Web. Для меня все еще удивительно, что ребята, создавшие gRPC Web, это сами ребята из Google, Сделали это позже, чем сделали gRPC Gateway.
gRPC‑Web — это генерация JS/TS‑клиента плюс reverse‑proxy (часто Envoy), который переводит запросы из браузера (обычно HTTP/1.1) в HTTP/2 к вашему gRPC‑серверу.
Client-streaming and half-duplex streaming
We don't plan to support client-streaming via Fetch/upload-streams (See Appendix on backgrounds on the Chrome Origin Trial). As a result, half-duplex bidi streaming won't be supported via Fetch/streams either.
Client-streaming and half-duplex bidi streaming will be addressed when Full-duplex streaming is supported via WebTransport (see below).
Ну в общем, это «типо» gRPC, это «типо» работает корректно, и «типо» удобен, да, доп расходы на настройку инфры для конвертации + возня с фронтенд разработчиками, чтобы заставить их пересесть на gRPC‑Web генератор:‑)
Выводы:
Да, вроде как это “почти” gRPC
Не работают корректно стримы
Дополнительные настройки reverse-proxy
Вам будет тяжело заставить frontend разработчиков пересесть на него :-)
Невозможно работать с файлами

Попытка №3: Twirp
И вот тут моя самая большая надежда была, не буду скрывать, почему? Ну потому что компания занимается стриминговой платформой, ну может они и стримы хотели сделать нормальные в web….
Заходя на их документацию, первое что я залез смотреть, механику вызовов и тут я немного удивился
curl --request "POST" \\
--header "Content-Type: application/json" \\
--data '{"subject": "World"}' \\
<http://localhost:8080/twirp/example.helloworld.HelloWorld/Hello>
Обычный curl, обычный json, так, что тут не так? Покопавшись в описании, а также сгенерировав код и покопавшись внутри я обнаружил забавную деталь Это не gRPC вовсе :-)
Даже не имитация, это просто генератор http сервера с описанием в proto формата, а также процедурным стилем rpc, а не rest парадигмы. Но, из преимуществ конечно осталось то, что есть удобные механики работы с http спецификой!

Но, может стримы хорошо работают же? А не тут то было, все также грустно, скажу больше, даже есть отдельный линтер для проверки, что если вы используете twirp - то не использовали вовсе стримы :D

Суть в чем, Twirp берёт proto как контракт, но не претендует быть gRPC: работает поверх HTTP/1.1 без стримов, упрощает модель до «RPC‑над‑REST». Но, может хоть удобно
Короче говоря, это попросту RPC фреймворк способный работать как с json так и с protobuf сериализацией, но под капотом там обычный http/1.1, в общем, провал :-)
Да, если что, они там уже его даже не развивают, последний коммит был год назад. Так что брать его совсем не рекомендую. И на десерт, затащив Twirp вы поломаете обратную совместимость с библиотеками работы с gRPC, придется заменять интерсепторы

Где Twirp уместен: нигде, он мертв.
Попытка №4: ConnectRPC — единая точка входа без внешнего прокси

Первое, что я увидел зайдя на документацию - подарило большую надежду!
grpcurl \\
-d '{"sentence": "I feel happy."}' \\
demo.connectrpc.com:443 \\
connectrpc.eliza.v1.ElizaService/Say
curl \\
--header 'Content-Type: application/json' \\
--data '{"sentence": "I feel happy."}' \\
<https://demo.connectrpc.com/connectrpc.eliza.v1.ElizaService/Say>
Так, это не просто вызов http ручки с protobuf сериализацией! Это полноценный gRPC, еще и http вызов стандартный работает, причем оба работают а одном порту

То есть единый сервер, но, поддерживающий два интерфейса? Да еще и поддерживает удобную работу с http спецификой!

То есть вроде как это нативный gRPC, но вдобавок еще и поддерживает rest? Так, я уже достаточно намок, но, не может быть все так хорошо, так что я пошел копать, работают ли стримы в web, и да, если вы не оптимист вы уже поняли ответ, опять нет полноценной поддержки, а из web будет вызываться конечно же опять таки просто http/1.1, ну и напоследок, финальный гвоздь в их библиотеку:

Полная поломка обратной совместимости с библиотеками для работы с gRPC. Но, покопавшись можно выяснить, что AnyRequest и AnyResponse - это интерфейсы, так что вы можете подменить имплементацию, можете же?

Вы все верно поняли, ребята сделали интерфейс, вложили в него приватные методы, чтобы вы не могли бы подменить реализацию :-)
Так что ни стримов в web ни обратной совместимости по библиотекам, да еще и все завязано на их экосистеме - фактически, это просто пропатченый twirp :-(
Да, сама библиотека местами удобная, но одновременно с этим имеет столько сложностей по переезду, что попросту решил избегать его использование (умрет, будет больно переезжать обратно).
Вывод: стоит избегать, завязывают на своей экосистеме, которая помимо того, что уступает стандартной gRPC-Ecosystem, так еще полностью завязана на их.
Так что выбрать в итоге?
gRPC-Gateway - все еще опережает всех развитостью
gRPC-Web - имеет перспективное будущее, ведь мы верим в Google, про их кладбище проектов стараемся не вспоминать :-)
Twirp - не смог таки набрать критическую массу, медленно увядает
ConnectRPC - создан для расширения экосистемы Buf, а не решения проблем
gRPC-Gateway |
gRPC-Web |
Twirp |
ConnectRPC |
---|---|---|---|
18.3K ⭐ |
8.7K ⭐ |
7.2K ⭐ |
3K ⭐ |
Удобно и для back и front и devops не парятся |
Удобно только для back |
Неудобно никому |
Неудобно никому |
Поддержка всего из мира WEB и из мира gRPC |
Полноценная работа с gRPC экосистемой |
Не работает gRPC экосистема из коробки |
Не работает gRPC экосистема из коробки |
Неудобно работать с файлами |
Не выйдет работать с файлами |
Не выйдет работать с файлами |
Не выйдет работать с файлами |
HTTP специфика |
Нет HTTP специфики |
HTTP специфика |
HTTP специфика |
Стримы! |
Нет стримов :( |
Нет стримов :( |
Нет стримов :( |
Самый крупный инструмент в области - поддержка сообщества |
Поддержка Google |
Заглохло развитие |
Развивается командой Buf |
P.S. После блокировок buf.build мы с товарищем сделали Git‑based пакетный менеджер для proto‑контрактов и самое классное, что на нас вышел классный и хороший обзор :-)
P.P.S. В отдельной статье разберу: конкретные флаги и конфиги для gRPC‑Gateway, чтобы подтянуть latency и RPS до «почти ConnectRPC», где именно теряются интерсепторы и как обойти это с минимальными побочками.
P.P.P.S. Да, кстати, я выложу подробные бенчмарки и сравнение всех технологий у себя в телеграмм канале :-)
Комментарии (4)
shai_hulud
08.09.2025 09:55Дак есть же websockets с кастомными фреймами, в чем проблема сделать симуляцию h2 потоков поверх него.
Heggi
08.09.2025 09:55Мы для себя выбрали grpc-web с помощью библиотеки protobuf-ts (гораздо удобнее гугловской), на беке dotnet (с нативной поддержкой) и python (с envoy).
Из стримов нам нужны только серверные, так что ограничения grpc-web нас не ограничивают.
S0mnium
А почему нельзя сделать реализацию на golang, точнее на webasm и юзать ее?
Prototik
Да, в целом, всё та же: браузеры. Никто не даст ни прямой доступ к сети, ни к крутилкам встроенного http клиента, ни к конкретный фреймам http2 потоков.