Протокол Mercure: технология и применение¶
Mercure — это открытый сетевой протокол, разработанный для передачи данных в реальном времени с сервера клиенту по технологии push-уведомлений. Протокол спроектирован как современная альтернатива WebSocket и Server-Sent Events (SSE), работающая поверх стандартного HTTP и использующая его инфраструктуру, включая прокси-серверы и системы аутентификации. Mercure был создан в 2018 году французским разработчиком Кевином Дюнгла и в первую очередь ориентирован на веб-приложения, построенные на платформе Symfony, хотя может применяться с любым языком программирования.
¶История и предпосылки создания
Появление Mercure связано с ограничениями существовавших на момент разработки технологий. WebSocket, хотя и обеспечивает полнодуплексную связь, требует поддержания долгоживущего соединения и не всегда корректно работает через корпоративные прокси и NAT. Server-Sent Events, в свою очередь, поддерживают только однонаправленную передачу и имеют ограничение на количество одновременных соединений с одним доменом в браузере. Протокол Mercure был представлен как решение, объединяющее простоту HTTP с возможностью мгновенной доставки событий. Первая стабильная версия спецификации была опубликована в 2020 году, после чего протокол был включён в экосистему фреймворка Symfony в качестве компонента Mercure Component.
¶Архитектура и принцип работы
Mercure использует модель «публикация-подписка» (pub/sub). Взаимодействие строится вокруг трёх основных участников: клиента, сервера публикации и концентратора (hub). Концентратор выступает центральным узлом, который принимает сообщения от серверов приложений и рассылает их подписанным клиентам.
Клиент устанавливает долгоживущее HTTP-соединение с концентратором с помощью стандартного механизма EventSource (Server-Sent Events). После установления соединения клиент отправляет запрос на подписку, указывая интересующие его темы (topics). Темы представляют собой URI, которые могут описывать конкретные ресурсы, например /books/123 или https://example.com/users/456`.
Сервер приложения, желающий уведомить клиентов об изменении данных, отправляет POST-запрос на конечную точку концентратора. В теле запроса передаётся содержимое уведомления и список тем, к которым это уведомление относится. Концентратор проверяет подлинность запроса и пересылает уведомление всем клиентам, подписанным на указанные темы.
¶Отличия от WebSocket и SSE
Ключевое отличие Mercure от WebSocket заключается в том, что соединение между клиентом и концентратором остаётся однонаправленным (сервер → клиент), что упрощает масштабирование и снижает нагрузку. В отличие от классического SSE, Mercure не требует от клиента знания адреса конкретного сервера приложений — все публикации проходят через единый концентратор, который может быть развёрнут отдельно от основного приложения. Это позволяет использовать преимущества HTTP/2, включая мультиплексирование, и обходить ограничение браузеров на шесть одновременных соединений с одним доменом.
¶Технические характеристики
Протокол определяет два типа конечных точек: точка подписки (для клиентов) и точка публикации (для серверов). Точка подписки доступна через GET-запрос с параметрами topic и Last-Event-ID для восстановления пропущенных событий. Точка публикации принимает POST-запросы с данными формы или JSON.
Аутентификация в Mercure построена на механизме подписанных токенов JWT. Для публикации сообщений сервер приложения должен обладать токеном с правом publish. Для подписки клиент может предоставить токен с правом subscribe, ограничивающий доступ к определённым темам. Если токен не передан, подписка разрешена только на публичные темы, объявленные в конфигурации концентратора.
Формат передаваемых данных основан на спецификации SSE: каждое событие содержит поле data, при необходимости дополняется полями id, event и retry. Mercure добавляет собственные расширения, такие как указание типа контента и приватность сообщения. Приватные сообщения (передаваемые с флагом private) доставляются только клиентам, прошедшим аутентификацию и имеющим право на подписку на соответствующую тему.
¶Применение и экосистема
Основная область применения Mercure — веб-приложения, требующие мгновенного обновления интерфейса без перезагрузки страницы. Типичные сценарии включают:
- уведомления о новых сообщениях в чатах и системах обмена сообщениями;
- обновление корзин интернет-магазинов и статусов заказов;
- совместное редактирование документов;
- трансляция биржевых котировок и спортивных результатов;
- синхронизация состояния между несколькими вкладками браузера.
Протокол наиболее плотно интегрирован в экосистему Symfony. Начиная с версии 5.2 фреймворк включает официальную поддержку Mercure, предоставляя разработчикам готовые классы для отправки обновлений из контроллеров и использования асинхронных компонентов Messenger. Однако реализация клиента доступна для JavaScript, а также для серверных языков через сторонние библиотеки, включая PHP, Go и Python.
¶Инфраструктурные решения
Для производственного использования предлагается готовый концентратор, написанный на языке Go. Он распространяется как отдельный исполняемый файл и может быть развёрнут на любом сервере. Концентратор поддерживает горизонтальное масштабирование через Redis или кластерную шину сообщений. Альтернативные реализации концентратора созданы на PHP и Node.js, однако официальная Go-версия остаётся эталонной.
¶Ограничения и недостатки
Несмотря на преимущества, протокол имеет ограничения. Основным недостатком считается необходимость разворачивать и поддерживать отдельный компонент — концентратор, что усложняет архитектуру по сравнению с прямым использованием WebSocket. Кроме того, механизм восстановления пропущенных событий требует, чтобы концентратор хранил историю сообщений, что увеличивает потребление памяти при высокой интенсивности публикаций.
Браузерная поддержка ограничена реализацией EventSource: все современные браузеры поддерживают технологию, однако Internet Explorer требует полифилла. При использовании HTTP/1.1 действует ограничение на количество одновременных соединений, что может потребовать применения HTTP/2 на уровне обратного прокси.
¶Сравнение с альтернативами
Выбор между Mercure, WebSocket и SSE зависит от конкретной задачи. WebSocket целесообразно применять для двустороннего обмена данными, например в онлайн-играх или редакторах кода. SSE подходит для простых сценариев доставки уведомлений с одного сервера. Mercure занимает промежуточное положение, предлагая удобный механизм публикации из любого компонента приложения и встроенную поддержку аутентификации и приватных каналов.
¶Источники
- Спецификация протокола Mercure (draft-version, официальный репозиторий проекта).
- Документация Symfony Mercure Component, Symfony 5.2–6.x.
- Официальная документация концентратора Mercure (mercure.rocks).
- Статья К. Дюнгла «Introducing Mercure» (2018).