Как веб-сайты/приложения узнают, что вы получили новое уведомление?

Как Gmail узнает, что вы получили электронное письмо, если вы не обновляете страницу? Или как Instagram мгновенно узнает, что вы получили запрос на подписку? Как правило, существует два подхода: запрос клиента или запрос сервера.

Наивный способ — короткий опрос (вытягивание клиента)

Примерно каждые 10 секунд мы отправляем запрос (опрос) на сервер для проверки обновлений. Плюс в том, что ресурсы сервера освобождаются почти сразу для каждого запроса, как только мы отправляем ответ.

Однако это может быть дорого для сервера, поскольку:

  • Количество запросов велико, генерирует много трафика
  • Обновления не мгновенные

Таким образом, короткие опросы клиентов обычно не используются в отрасли.

Долгий опрос (вытягивание клиента)

Идея состоит в том, что вместо того, чтобы клиент постоянно опрашивал сервер, мы хотим, чтобы сервер отправлял данные клиенту, как только происходит обновление. Однако серверы не могут случайным образом передавать данные клиентам, поскольку клиенты не прослушивают открытый порт и не принимают входящие соединения. Итак, нам нужно сохранить постоянное соединение, инициированное клиентом.

Это основано на Комете, и принцип его работы заключается в том, что вы открываете запрос к серверу и ждете его ответа в течение длительного периода времени. Сервер намеренно не отвечает сразу, а ждет, пока не придет уведомление, и отвечает. Чтобы поддерживать соединение, клиент и сервер должны время от времени отправлять друг другу пакеты.

Следует отметить несколько незначительных проблем, в основном:

  • Тайм-ауты (Подключение закрывается прокси-сервером, если оно бездействует слишком долго)
  • Каждый поток блокируется до тех пор, пока не будет получен ответ для php/apache (однако любой асинхронный подход, такой как Node, решает эту проблему)

Ниже приведена диаграмма, которая иллюстрирует, как оба эти механизма работают.

Для iOS это делается через серверы Apple, так что телефон имеет только одно постоянное подключение к серверам Apple, а затем как разработчик мы проксируем уведомления через их серверы клиенту.

Для Android мы можем бесплатно использовать Firebase Cloud Messaging как централизованный сервис.

Приведенных выше моделей было достаточно для ранних веб-приложений, поскольку ранние веб-сайты отображали только статический контент. Но по мере развития Интернета возникла необходимость разрешить серверам отправлять данные клиентам без предварительного запроса клиента. Это привело к появлению в 2000-х годах технологии push-уведомлений.

Поскольку модель запроса-ответа HTTP не была предназначена для этих случаев использования, были изобретены другие механизмы. Этими механизмами являются веб-сокеты и события, отправленные сервером (SSE).

Веб-сокеты (серверная отправка)

WebSocket — это просто постоянное соединение между клиентом и сервером. Он имеет полнодуплексные каналы связи по одному TCP-соединению.

Это имеет меньшие накладные расходы, чем полудуплексные альтернативы, такие как вышеупомянутый опрос клиента, и облегчает передачу данных в реальном времени с сервера и на сервер. Таким образом, нам не нужно опрашивать сервер всякий раз, когда мы хотим получить ответ в реальном времени.

Некоторые библиотеки, такие как Socket.IO, на самом деле имеют собственную иерархию, а это означает, что она будет выполнять длинный/короткий опрос клиента в случае сбоя WebSocket.

События, отправленные сервером (отправленные сервером)

В отличие от WebSockets, у которых есть собственный протокол, SSE передаются по HTTP и являются однонаправленными. После того как между сервером и клиентом установлено HTTP-соединение, сервер может отправлять автоматические обновления.

Думайте о SSE как о долго выполняющемся HTTP-запросе, который уведомляет клиента всякий раз, когда сервер получает обновление. SSE спроектированы так, чтобы быть более эффективными, чем длительный опрос, и имеют такие функции, как автоматическое повторное подключение, идентификаторы событий и возможность отправки произвольных событий.

В двух словах, когда использовать каждый:

Короткий опрос: никогда.
Длинный опрос: простой в реализации, можно использовать, когда вам не нужны слишком сложные решения
WebSockets : в основном для игр, но не так надежен для таких сценариев, как гостевые сети Wi-Fi или внутренние сети с брандмауэром, где сокеты могут дать сбой и пройти может только HTTP
Отправленные сервером события: используйте, когда вы нужна эффективность или масштабируемость

Ресурсы: