Centrifuge — так просто, как возможно, но не проще этого

в 7:04, , рубрики: asynchronous, jquery, open source, python, sockjs, tornado, WebSocket, zeromq, Блог компании Mail.Ru Group, метки: , , , , , , ,

Centrifuge — так просто, как возможно, но не проще этого
Привет!

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

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

Давайте посмотрим, что нам предлагает Центрифуга:

var centrifuge = new Centrifuge({
    url: 'http://localhost:8000/connection',
    token: 'TOKEN',
    project: 'PROJECT_ID',
    user: 'USER_ID'
});
 
centrifuge.on('connect', function() {
    centrifuge.subscribe('public:comments', function(message) {
        // message from channel received
    });
});

Вполне легко и просто, правда? Но возможно ли сделать еще проще?

В общем случае, пожалуй, нет. Конец статьи!

Стоп, стоп, конечно же нет, давайте посмотрим на частный случай. Если ваше веб-приложение требует достаточно сложной логики подписок, публикаций, менеджмента каналов, то скорее всего вариант, который я опишу ниже, не для вашего сайта. Однако, большинство веб-приложений не стремятся выжать максимум реалтаймовых возможностей — и все что им нужно — это слушать определенные каналы, которые динамически не меняются, получать события и реагировать на них, в большинстве случаев просто отрисовывая изменения на веб-странице. Это комментарии, счетчики, уведомления, графики и многое другое.

Многие из вас слышали о Knockout, AngularJS. Одно из средств, применяемых этими библиотеками — вынесение описания логики приложения в html страницы. Задавая атрибуты и их значения, вы можете легко менять поведение на желаемое. Что если воспользоваться html и в нашем случае?

Посмотрим на подключение к Центрифуге. Нужно передать адрес, токен, идентификатор пользователя и идентификатор проекта. Клиентская часть узнает нужные значения от бэкенда. Имена нужных каналов для подписки также передает в шаблон бэкенд. Как сообщить эти данные джаваскрипту?

Рассмотрим самые очевидные варианты. Можно передать эти данные в виде JSON на вход инициализирующей функции. А можно отрендерить данные на веб-странице как атрибуты html-элементов, а затем из кода обращаться к нужным элементам, брать значения их свойств и использовать. И этот второй вариант мне представляется наиболее гибким. Настолько гибким, что подобным образом программист, желающий использовать Центрифугу, может поступать на всех страничках с реал-тайм элементами.

Поэтому, чтобы вам не пришлось писать свою обертку, я написал jQuery плагин centrifuge.dom.js:

<script src="raw.github.com/FZambia/centrifuge/master/javascript/centrifuge.dom.js"></script>

Будучи подключенным, он цепляет данные из отрендеренных на страничке html-элементов, сам создает на их основе подключение к Центрифуге, подписывается на каналы. А когда приходит сообщение — триггерит событие на html-элементе с полученными данными.

Всё что остается вам в данном случае — описать, как будет реагировать веб-страница на полученное сообщение, то есть:

$(' #html-element').on('centrifuge.message', function(message) {
    console.log(message.data);
});

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

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

1) В основном шаблоне инициализируем плагин:

$(function(){
    $.centrifuge_dom({});
});

2) Также в основном шаблоне прописываем постоянные html-элементы с токеном, адресом и идентификаторами:

<div id="centrifuge-address" data-centrifuge-value="{{ centrifuge_address }}"></div>
<div id="centrifuge-token" data-centrifuge-value="{{ centrifuge_token }}"></div>
<div id="centrifuge-user" data-centrifuge-value="{{ centrifuge_user }}"></div>
<div id="centrifuge-project" data-centrifuge-value="{{ centrifuge_project }}"></div>

Здесь используется синтаксис django-шаблонов, данные об адресе, токене, ID юзера и проекта предоставляет бэкенд вашего приложения.

3) На странице с комментариями добавляем html-элемент с именем канала:

<div class="centrifuge" id="comments-handler" data-centrifuge-channel="comments" data-centrifuge-namespace=”public”></div>

4) И на этой же страничке c комментариями добавляем javascript:

$(function() {
    $(‘#comments-handler’).on(‘centrifuge.message, function(message) {
        $(‘body’).append(message.data);
    });
});

Всё!

Более того, теперь, чтобы добавить новый реал-тайм элемент на любую страницу, вам потребуется выполнить только последние 2 пункта.

Вариант не учитывает возможных ошибок, в некоторых случаях вам и не потребуется их отлавливать. Но в любом случае плагин предоставляет возможность повесить дополнительные обработчики событий на html-элемент, такие как centrifuge.error, centrifuge.disconnect, чтобы должным образом среагировать.

Та ли это идеальная простота, о которой говорил Альберт Эйнштейн (его знаменитый афоризм в основе заголовка данной статьи) — покажет время.

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

Центрифуга доросла до версии 0.3.1.

Теперь для PUB/SUB механизма можно использовать Redis вместо ZeroMQ. А в случае если вам достаточно одного инстанса Центрифуги, то можно обойтись вообще без них.

Можно установить Центрифугу без ненужных вам зависимостей, используя флаги setup.py: --without-zmq, --without-redis, --without-postgresql, --without-mongodb

Переделан веб-интерфейс, он теперь хорошо выглядит на мобильных устройствах и, на мой взгляд, стал гораздо симпатичней.

Centrifuge — так просто, как возможно, но не проще этого

Из раздела “менеджмент проекта” можно публиковать JSON в каналы (для этого используется Ace editor), a также запрашивать presence, history данные канала и отписывать пользователя по ID.

Появилось API для структуры проектов и пространств имен — абсолютно все действия теперь можно выполнять не используя веб-интерфейс.

На этом пока всё, до новых встреч, друзья!

Автор: FZambia

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js