gRPC, GraphQL и реальное время
RPC и транспорты реального времени, между которыми выбирает аналитик — gRPC и Protobuf, GraphQL против REST, WebSocket/SSE/long-polling, вебхуки и их защита, идентификаторы корреляции.
13 вопросов
JuniorТеорияОчень частоЧто такое polling, что такое long polling и во что каждый обходится серверу?
Что такое polling, что такое long polling и во что каждый обходится серверу?
Polling — клиент запрашивает новые данные через фиксированный интервал; большинство ответов пусты, добавляя задержку до одного интервала. Long polling держит запрос открытым до данных или таймаута, затем открывает заново. Это убирает пустые round-trip, но занимает соединение сервера на каждого ждущего.
Типичные ошибки
- ✗Путать, кто держит запрос открытым (long polling), а кто бьёт по таймеру (polling)
- ✗Считать polling бесплатным — пустые ответы всё равно стоят запросов и задержки
- ✗Забывать, что long polling занимает соединение сервера на каждого ждущего клиента
Уточняющие вопросы
- →Когда long polling перестаёт масштабироваться и что приходит на смену?
- →Как выбрать интервал polling между свежестью и нагрузкой?
JuniorТеорияОчень частоЧто такое webhook и в чём его главные плюсы и минусы по сравнению с polling?
Что такое webhook и в чём его главные плюсы и минусы по сравнению с polling?
Webhook — обратный вызов API: вместо того чтобы вы опрашивали провайдера, он сам шлёт HTTP POST на зарегистрированный вами URL при событии. Плюс — эффективность push: данные приходят сразу, без пустых лишних запросов. Минусы — нужно держать публичный, защищённый, всегда доступный endpoint и самому обрабатывать пропуски и дубли доставки.
Типичные ошибки
- ✗Думать, что webhook — это более частый polling клиента, а не push от провайдера к вам
- ✗Считать доставку гарантированной, поэтому повторы и сверка якобы не нужны
- ✗Забывать, что webhook требует публичного, защищённого, всегда доступного endpoint
Уточняющие вопросы
- →Как защитить endpoint webhook от поддельных вызовов?
- →Что делать, если webhook так и не доставлен?
MiddleТеорияОчень частоЧто такое WebSocket, как устанавливается соединение и когда он действительно нужен?
Что такое WebSocket, как устанавливается соединение и когда он действительно нужен?
WebSocket — постоянное полнодуплексное соединение поверх TCP-сокета, где обе стороны шлют сообщения. Начинается как HTTP-запрос с заголовком Upgrade: websocket; при согласии сервера соединение меняет протокол. Нужен для двунаправленного трафика с низкой задержкой, а не редких обновлений.
Типичные ошибки
- ✗Думать, что WebSocket односторонний, а не полнодуплексный
- ✗Считать, что он открывает новое соединение на каждое сообщение, а не остаётся постоянным
- ✗Тянуться к WebSocket там, где хватило бы одностороннего SSE или polling
Уточняющие вопросы
- →Как HTTP-рукопожатие Upgrade меняет протокол на одном соединении?
- →Почему для только-серверных обновлений предпочесть SSE, а не WebSocket?
JuniorТеорияЧастоЧто такое удалённый вызов процедуры (RPC) и чем он отличается от REST на уровне контракта?
Что такое удалённый вызов процедуры (RPC) и чем он отличается от REST на уровне контракта?
RPC делает удалённый вызов похожим на вызов локальной функции: клиент вызывает именованную операцию вроде getUser с аргументами, транспорт скрыт. REST выставляет ресурсы по URL через HTTP-методы. Контракт RPC — список методов и параметров; контракт REST — ресурсы и методы над ними.
Типичные ошибки
- ✗Думать, что RPC и REST различаются только транспортом или шифрованием, а не формой контракта
- ✗Считать, что REST выставляет методы, а RPC — ресурсы (на самом деле наоборот)
- ✗Полагать, что удалённый вызов процедуры не может пересекать сеть
Уточняющие вопросы
- →Когда RPC-стиль API подойдёт лучше REST?
- →Как gRPC развивает базовую модель RPC?
MiddleТеорияЧастоЧто такое GraphQL, какие проблемы REST он решает и во что обходится — проблема запросов N+1 и кэширование?
Что такое GraphQL, какие проблемы REST он решает и во что обходится — проблема запросов N+1 и кэширование?
GraphQL — язык запросов с одним endpoint и типизированной схемой: клиент запрашивает ровно нужные поля одним запросом. Это решает over-fetching и under-fetching REST. Цена: per-URL HTTP-кэширование ломается, ведь всё идёт в один endpoint, а наивный резолвер упирается в проблему N+1 — поэтому добавляют батчинг.
Типичные ошибки
- ✗Думать, что GraphQL использует много URL как REST, а не один endpoint
- ✗Считать, что GraphQL улучшает per-URL HTTP-кэширование, а не усложняет его
- ✗Полагать, что проблема N+1 исчезает сама без батчинга
Уточняющие вопросы
- →Как dataloader батчит вызовы резолвера против проблемы N+1?
- →Почему HTTP-кэширование сложнее с единым endpoint GraphQL?
MiddleТеорияЧастоЧто такое Server-Sent Events (SSE) и чем они отличаются от WebSocket и от long polling?
Что такое Server-Sent Events (SSE) и чем они отличаются от WebSocket и от long polling?
SSE — односторонний поток: клиент открывает долгоживущее HTTP-соединение, а сервер шлёт текстовые события, переподключаясь автоматически. В отличие от WebSocket он только сервер-к-клиенту поверх обычного HTTP — проще и дружелюбен к proxy. В отличие от long polling держит соединение открытым.
Типичные ошибки
- ✗Думать, что SSE двунаправленный как WebSocket, а не только сервер-к-клиенту
- ✗Считать, что SSE нужен не-HTTP протокол или порт
- ✗Забывать, что SSE переподключается сам, в отличие от рукописного long polling
Уточняющие вопросы
- →Почему SSE дружелюбнее к proxy, чем WebSocket?
- →Когда одностороннего потока SSE перестаёт хватать?
MiddleТеорияЧастоКакой транспорт вы выберете для чата, для биржевого тикера и для межбанковского перевода — и почему?
Какой транспорт вы выберете для чата, для биржевого тикера и для межбанковского перевода — и почему?
Чату нужен WebSocket — обе стороны шлют сообщения непрерывно, подходит полный дуплекс. Тикер — односторонний высокочастотный push, подходит SSE или WebSocket. Межбанковский перевод не реального времени — одна надёжная, идемпотентная, аудируемая операция, поэтому подходит запрос/ответ или очередь, а не сокет.
Типичные ошибки
- ✗Навязывать один транспорт всем трём вместо подбора под направление и гарантии
- ✗Считать банковский перевод стримингом, а не надёжной одиночной операцией
- ✗Путать односторонний поток тикера с двунаправленным чатом
Уточняющие вопросы
- →Почему переводу важнее идемпотентность, чем низкая задержка?
- →Когда вы перенесёте поток тикера с SSE на WebSocket?
MiddleДизайнЧастоВаша система выставляет публичный webhook-endpoint, который платёжный провайдер вызывает на каждую транзакцию. Опишите, как вы защитите этот endpoint, чтобы поддельный или повторно отправленный запрос не мог вызвать ложное событие оплаты, и опишите, что ваша система должна делать, когда легитимный webhook так и не приходит — например, доставка провайдера истекла по таймауту или ваш endpoint ненадолго упал. Раскройте и аутентификацию входящего вызова, и восстановление пропущенного.
Ваша система выставляет публичный webhook-endpoint, который платёжный провайдер вызывает на каждую транзакцию. Опишите, как вы защитите этот endpoint, чтобы поддельный или повторно отправленный запрос не мог вызвать ложное событие оплаты, и опишите, что ваша система должна делать, когда легитимный webhook так и не приходит — например, доставка провайдера истекла по таймауту или ваш endpoint ненадолго упал. Раскройте и аутентификацию входящего вызова, и восстановление пропущенного.
Защитите его проверкой подписи: провайдер подписывает тело общим секретом (HMAC), а вы пересчитываете и сравниваете, отклоняя несошедшееся. Добавьте проверку метки времени или nonce против повторов и только HTTPS. Для пропусков не считайте webhook единственным путём — сделайте обработчики идемпотентными и сверяйтесь, опрашивая API провайдера.
Типичные ошибки
- ✗Доверять секретному URL или IP источника вместо проверки подписи
- ✗Считать доставку гарантированной, поэтому сверка якобы не нужна
- ✗Пропускать идемпотентность, из-за чего повтор провайдера обрабатывает событие дважды
Уточняющие вопросы
- →Как метка времени или nonce мешает повторно отправить перехваченный запрос?
- →Почему обработчик webhook должен быть идемпотентным, чтобы повторы были безопасны?
MiddleТеорияИногдаЧто такое correlation ID, кто его генерирует и как он проходит по смешанной sync- и async-цепочке?
Что такое correlation ID, кто его генерирует и как он проходит по смешанной sync- и async-цепочке?
Correlation ID — токен на запросе, связывающий каждую строку лога и каждый переход одной операции между сервисами. Он генерируется один раз на входе — на gateway или первом сервисе — если вызывающий не передал. Он едет в HTTP-заголовке на sync-вызовах и в метаданных сообщения на async, без изменений на каждом сервисе.
Типичные ошибки
- ✗Думать, что каждый сервис генерирует свой ID, а не пробрасывает один без изменений
- ✗Считать, что он работает только на синхронных вызовах, а не через async-сообщения
- ✗Генерировать его в конце потока, а не на входе
Уточняющие вопросы
- →Как correlation ID пересекает границу очереди сообщений?
- →Чем он отличается от span ID на каждый переход в распределённой трассировке?
MiddleТеорияИногдаЧто такое gRPC, какой транспорт и контракт он использует и когда он выигрывает у REST?
Что такое gRPC, какой транспорт и контракт он использует и когда он выигрывает у REST?
gRPC — RPC-фреймворк Google поверх HTTP/2, кодирующий сообщения через Protobuf по строгому контракту .proto. HTTP/2 даёт мультиплексирование и стримы; Protobuf — компактную бинарную нагрузку и сгенерированные заглушки. Он выигрывает у REST на бэкенд-к-бэкенду; REST лучше для публичных браузерных API.
Типичные ошибки
- ✗Думать, что gRPC шлёт JSON или XML, а не бинарный Protobuf
- ✗Считать, что gRPC нативен для браузера и лучше всего для публичных веб-API
- ✗Забывать, что контракт
.protoгенерирует клиентские и серверные заглушки
Уточняющие вопросы
- →Почему gRPC нужен HTTP/2, а не HTTP/1.1?
- →Почему gRPC неудобно вызывать напрямую из браузера?
MiddleТеорияИногдаЧто такое Protobuf, чем он отличается от JSON на проводе и что даёт контракт .proto?
Что такое Protobuf, чем он отличается от JSON на проводе и что даёт контракт .proto?
Protobuf — бинарный формат сериализации. Он шлёт компактные тегированные байты, а не читаемый текст JSON, поэтому нагрузка меньше, но нечитаема без схемы. Файл .proto задаёт тегированные поля и генерирует код; стороны развиваются независимо, пока теги не переиспользуют.
Типичные ошибки
- ✗Думать, что Protobuf — читаемый текст как JSON, а не тегированный бинарь
- ✗Считать, что нагрузка Protobuf больше или медленнее JSON
- ✗Переиспользовать или перенумеровывать теги полей, тихо ломая контракт
Уточняющие вопросы
- →Как числовой тег поля обеспечивает обратно совместимую эволюцию?
- →Когда JSON всё же лучше Protobuf?
SeniorДизайнРедкоМобильный экран сейчас делает 12 отдельных REST-вызовов для отрисовки, что медленно на мобильной сети. На столе три варианта: выставить endpoint GraphQL, построить сервис Backend-for-Frontend (BFF), который приложение вызывает один раз, или добавить REST-агрегат, собирающий 12 вызовов на сервере. Обоснуйте, что выберете и почему, учитывая число round-trip на мобильной задержке, кто владеет логикой сборки, кэширование и сколько разных типов клиентов надо обслуживать.
Мобильный экран сейчас делает 12 отдельных REST-вызовов для отрисовки, что медленно на мобильной сети. На столе три варианта: выставить endpoint GraphQL, построить сервис Backend-for-Frontend (BFF), который приложение вызывает один раз, или добавить REST-агрегат, собирающий 12 вызовов на сервере. Обоснуйте, что выберете и почему, учитывая число round-trip на мобильной задержке, кто владеет логикой сборки, кэширование и сколько разных типов клиентов надо обслуживать.
Все три сворачивают 12 round-trip в один, поэтому выбирайте по владению и числу клиентов. REST-агрегат подходит одному экрану с фиксированной нагрузкой. BFF подходит, когда приложению нужна своя форма, которой владеет его команда. GraphQL — когда многим клиентам нужны разные поля. Цена — сборка на сервере и слабее кэширование.
Типичные ошибки
- ✗Считать GraphQL, BFF и REST-агрегат взаимозаменяемыми без компромиссов
- ✗Полагать, что один BFF должен сразу обслуживать каждый тип клиента
- ✗Верить, что агрегация улучшает per-URL кэширование, а не ослабляет его
Уточняющие вопросы
- →Когда BFF становится лучше GraphQL для одного приложения?
- →Почему сворачивание round-trip важнее на мобильной сети?
SeniorДизайнРедкоИзменение статуса заказа должно дойти до трёх потребителей: веб-клиента с открытой страницей заказа, мобильного приложения клиента, которое может быть свёрнуто или офлайн, и бэкенд-системы компании-партнёра. Для каждого из трёх выберите транспорт доставки — например WebSocket или SSE, push-уведомление, webhook или polling — и обоснуйте выбор по связности потребителя, его требованиям к задержке и тому, кто владеет endpoint. Объясните, почему один транспорт не может хорошо обслужить все три.
Изменение статуса заказа должно дойти до трёх потребителей: веб-клиента с открытой страницей заказа, мобильного приложения клиента, которое может быть свёрнуто или офлайн, и бэкенд-системы компании-партнёра. Для каждого из трёх выберите транспорт доставки — например WebSocket или SSE, push-уведомление, webhook или polling — и обоснуйте выбор по связности потребителя, его требованиям к задержке и тому, кто владеет endpoint. Объясните, почему один транспорт не может хорошо обслужить все три.
Для открытой веб-страницы — SSE или WebSocket. Для мобильного приложения — платформенный push: часто свёрнуто или офлайн, не удержит сокет. Для бэкенда партнёра — webhook, ведь у него публичный endpoint. Один транспорт не обслужит все три: разная связность, владелец endpoint и терпимость к задержке.
Типичные ошибки
- ✗Навязывать один транспорт всем трём потребителям с разной связностью
- ✗Ждать, что свёрнутое или офлайн приложение удержит живой сокет
- ✗Давать браузеру или телефону webhook-endpoint, который вызывает сервер
Уточняющие вопросы
- →Почему свёрнутое мобильное приложение не может полагаться на удерживаемый сокет?
- →Почему webhook — естественный выбор для бэкенда партнёра?