Webhook, polling, SSE, WebSocket для системного аналитика

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Карьерник — Duolingo для аналитиков: 10 минут в день тренируй SQL, Python, A/B, статистику, метрики и ещё 3 темы собеса. 1500+ вопросов в Telegram-боте. Бесплатно.

Зачем сравнение спрашивают

Системный аналитик описывает интеграцию: внешняя система должна узнавать о событиях нашей. На собесе классический кейс: «банк должен получать уведомления о новых платежах. Опишите механизм». Ответ «отправлять каждые 10 секунд GET-запрос» — провал. Это polling, и он плохо масштабируется.

Главная боль без понимания вариантов — partner-команды строят polling на 1М запросов/день вместо webhook на 10k событий/день. Нагрузка вырастает в 100 раз без увеличения ценности. Аналитик должен знать матрицу: когда какой вариант.

Polling

Клиент периодически дёргает сервер с вопросом «есть что-то новое?»

Client: GET /events?since=12345    → 200 [empty]
... (через 10 сек)
Client: GET /events?since=12345    → 200 [event1, event2]
Client: GET /events?since=12347    → 200 [empty]

Плюсы:

  • Простейшая реализация
  • Работает через любые прокси/firewall
  • Stateless: сервер не помнит клиентов

Минусы:

  • Большинство запросов пустые → пустая нагрузка на сеть и сервер
  • Высокая latency: средняя задержка = половина интервала
  • Не масштабируется: 1k клиентов × 1 запрос/сек = 1k RPS впустую

Когда применять: редкие события, простота важнее эффективности, нет возможности webhook (клиент не публичный).

Long-polling

Клиент шлёт запрос, сервер не отвечает сразу — ждёт события или таймаут.

Client: GET /events?since=12345    → (сервер ждёт 30 сек)
Server: → 200 [event1]              (когда событие пришло)
Client: GET /events?since=12346    → (сервер ждёт)

Плюсы:

  • Меньше пустых запросов
  • Низкая latency: событие приходит почти мгновенно

Минусы:

  • Сервер держит открытое соединение per-client → шкалируется хуже polling по памяти
  • Прокси/балансировщики могут резать долгие запросы (таймауты 30-60 сек)
  • Сложнее мониторинг: «висит» — нормально или badly?

Используется в legacy чат-системах. В современных стеках вытеснен SSE и WebSocket.

Webhook

Сервер вызывает HTTP-endpoint клиента, когда событие происходит.

... (на нашей стороне произошёл платёж)
Server (наш): POST https://partner.com/webhooks/payments
              {payment_id: 123, amount: 1000}
Client (партнёра): 200 OK

Плюсы:

  • Минимальный трафик: один запрос на событие
  • Низкая latency: событие → доставка
  • Сервер не держит соединения

Минусы:

  • Партнёр должен быть публично доступен (или туннель/proxy)
  • Нужна обработка retry/доставки (партнёр временно недоступен → повторять)
  • Нет гарантии порядка (если несколько событий за секунду — могут прийти не в том порядке)
  • Безопасность: HMAC подпись, проверка origin

Стандарт описания в ТЗ:

  • URL endpoint партнёра, метод (обычно POST)
  • Формат тела (JSON schema, Avro)
  • Подпись (HMAC SHA-256 заголовок)
  • Retry-policy: коды для ретраев (5xx, 408, 429), backoff, max attempts, dead-letter queue
  • Idempotency-key для дедупликации при ретраях
  • Versioning: как добавляем новые поля без поломки старых клиентов

Server-Sent Events (SSE)

HTTP-based unidirectional stream сервер → клиент.

Client: GET /events
        Accept: text/event-stream

Server: HTTP/1.1 200 OK
        Content-Type: text/event-stream

        data: {"id": 1, "amount": 100}\n\n

        data: {"id": 2, "amount": 200}\n\n
        ...

Плюсы:

  • Native в браузерах через EventSource
  • Авто-reconnect и last-event-id (после сбоя клиент продолжит с того же места)
  • Простая реализация на сервере (просто HTTP-ответ с keep-alive)
  • Кеши/proxy дружественны (это HTTP)

Минусы:

  • Только сервер → клиент, не bidirectional
  • Только текст/UTF-8 (бинарь — base64)
  • Не подходит для мобильных приложений напрямую (хотя есть библиотеки)

Когда применять: stock tickers, push notifications в браузере, live feed, прогресс долгой задачи.

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

WebSocket

Двусторонний (full-duplex) канал поверх TCP, начинается с HTTP upgrade.

Client: GET /ws
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Key: ...

Server: HTTP/1.1 101 Switching Protocols
        Upgrade: websocket

(после этого — бинарные/текстовые фреймы в обе стороны)

Плюсы:

  • Bidirectional: и сервер, и клиент могут отправлять
  • Низкая latency, бинарь поддерживается
  • Поддерживается всеми современными браузерами
  • Один канал на множество событий

Минусы:

  • Сервер держит соединение → memory per-client
  • Не stateless → балансировщики L7 нужны с sticky sessions
  • Не кешируется через CDN
  • Прокси-настройки иногда блокируют (HTTPS upgrade through proxy)
  • Сложнее реализация и operations

Когда применять: чат, multiplayer-игры, collaborative editing, торговля в реальном времени, диспетчерские системы.

Матрица выбора

Сценарий Выбор
Партнёрская система получает редкие события (платежи, статусы заказов) Webhook
Браузер показывает live-обновления (тикер, fee live) SSE
Чат, многопользовательская игра WebSocket
Мобилка, несколько событий в час Push-уведомления (FCM/APNS) или polling
Партнёр не имеет публичного endpoint Polling или long-polling
Прогресс долгой задачи в браузере SSE или polling по статусу
Контроль над сервером невелик, инфра простая Polling
Bidirectional низколатентное взаимодействие WebSocket

Частые ошибки

Polling вместо webhook когда возможно. Если партнёр имеет публичный URL — webhook эффективнее на 1-2 порядка.

Не описывать retry в webhook. Партнёр упал, не получил → событие потеряно. Описать политику ретраев и dead-letter.

Webhook без HMAC-подписи. Любой может симулировать событие на endpoint партнёра. Подпись + verification обязательны.

WebSocket для редких событий. Открытое соединение на пустую переписку — ресурсы впустую. Push-уведомления или SSE достаточно.

SSE для bidirectional. SSE — только сервер → клиент. Если нужно двустороннее — WebSocket или комбинация SSE + POST.

Long-polling без таймаутов. Соединение висит часами, балансировщик режет, клиент думает «всё нормально». Явный таймаут (30-60 сек) и reconnect.

Webhook без idempotency. Партнёр получает webhook повторно после ретрая, начисляет бонус дважды. Idempotency-Key в headers + дедуп на стороне партнёра.

Связанные темы

FAQ

Webhook это REST?

Не совсем. Webhook — это паттерн «обратного вызова» через HTTP. Технически — POST-запрос на endpoint клиента. Сам endpoint — REST-стиля (URL ресурса), но семантика — push.

WebSocket поверх HTTP?

Начало — HTTP upgrade (handshake). Дальше — TCP-соединение с собственным фреймовым протоколом. С точки зрения proxy — это HTTPS-туннель.

Что выбрать между SSE и WebSocket для уведомлений в браузере?

Если только сервер → клиент, текст, простая интеграция — SSE. Если нужны двусторонние сообщения, бинарь, низкая latency — WebSocket.

Как доставлять события мобильному приложению?

Push-уведомления (FCM для Android, APNS для iOS). Когда приложение открыто — может быть WebSocket для real-time чата. Polling — фоном при низкой важности.

Можно ли использовать WebSocket для машинных интеграций (server-to-server)?

Можно, но обычно избыточно. gRPC streaming, Kafka, webhooks — более стандартные решения для server-to-server. WebSocket чаще для browser-to-server.

Это официальная информация?

Нет. Статья основана на RFC 6455 (WebSocket), HTML5 SSE spec, общей практике интеграционной архитектуры.


Тренируйте системный анализ — откройте тренажёр с 1500+ вопросами для собесов.