24 December 2009

Realplexor: производительный Comet-сервер с API для PHP и Javascript (realtime)

High performance
Dklab Realplexor — это Comet-сервер, позволяющий держать одновремено сотни тысяч долгоживущих открытых HTTP-соединений с браузерами пользователей. JavaScript-код, запущенный в браузере, подписывается на один или несколько каналов Realplexor-а и вешает обработчик на поступление данных. Сервер может в любой момент записать сообщение в один из таких каналов, и оно будет моментально передано всем подписчикам (хоть одному, хоть тысяче), в режиме реального времени и с минимальной нагрузкой для сервера.

Хотя идейным вдохновителем Realplexor-а был предыдущий проект, dklab_multiplexor, код Realplexor-а не имеет с ним практически ничего общего. Поэтому я и решил сменить название. Несопоставимы также возможности продуктов (см. ниже), да и размер кода увеличился в 7 раз.

Realtime-направление сейчас довольно активно развивается на Западе, и в нем особенно выделяется продукт Tornado — событийно-ориентированный веб-сервер на языке Python. Правда, Tornado — это не столько Comet-сервер, сколько инструмент, с помощью которого можно запрограммировать «в том числе» и Comet-сервер. Ключевые слова: Comet, Push Server, Long polling, JavaScript, XMLHttpRequest.

Главные преимущества Realplexor-а:
  • простота использования: наличие API для JavaScript, API для PHP (в будущем — и для других языков);
  • простота конфигурирования;
  • широкий функционал (либо отстутствующий, либо недоступный напрямую в аналогах).

Лучше один раз увидеть...


Я сделал отдельную онлайн-песочницу, чтобы продемонстрировать функционал нового Realplexor-а и то, для чего вообще нужны Comet-серверы (кстати, это физически тот же самый демон Realplexor-а, что использует мой новый стартап РуТвит). Песочница реализует что-то типа многоканального чата: зайдя, вы получите как будто бы 2 независимых «браузера», запущенных на разных компьютерах.
  • Верхний «браузер» отображает каналы — в них моментально появляются новые сообщения, как только кто-то их туда отправляет на стороне сервера. Конечно же, эту страницу могут просматривать одновременно сотни тысяч пользователей, и они все будут видеть одно и то же (реализовано с использованием Realplexor JavaScript API). Можно «на лету» добавлять новые каналы (подписка) или скрывать уже имеющиеся (отписка).
  • Нижний браузер содержит формы, позволяющие добавлять сообщение в произвольный канал, указав его имя. Форма AJAX-ом отправляется на сервер, и уже там PHP-скрипт записывает в Realplexor полученный текст через PHP API. (И да, так можно чатиться.)
По умолчанию на странице открыто 3 канала с именами Alpha, Beta и RuTvit. Но, конечно, вы можете закрыть эти каналы и открыть новые. Вот, например, страница с единственным открытым каналом по имени Habrahabr: http://rutvit.ru/realplexor/demo?ids=Habrahabr.



Песочница демонстрирует следующие функции Realplexor-а:
  • Одновременное прослушивание нескольких каналов с динамическим добавлением/удалением каналов.
  • Одновременную отправку сообщения в несколько каналов (фактически, получился чат).
  • Обновление «на лету» списка онлайн-каналов (каналов, которые слушает хотя бы один пользователь).
  • Искользование JavaScript API и PHP API, которые идут в поставке Realplexor-а.
Ниже приведены выдержки из кода этой песочницы (с точностью до верстки и с адаптацией под данную статью), иллюстрирующие применение API Realplexor-а.

Листинг 1: Интересные выдержки из кода песочницы: JavaScript
// Create Dklab_Realplexor client.
var realplexor = new Dklab_Realplexor(
    "http://rpl.YourSite.com/",  // Realplexor's engine URL; must be a sub-domain
    "demo_" // namespace
);
 
// Subscribe a callback to channel Alpha.
realplexor.subscribe("Alpha", function (result, id) {
    alert(result);
});
 
// Subscribe a callback to channel Beta.
realplexor.subscribe("Beta", function (result, id) {
    div.innerHTML = result;
});
 
// Apply subscriptions. Сallbacks are called asynchronously on data arrival.
realplexor.execute();

Листинг 2: Интересные выдержки из кода песочницы: PHP
// Create new API object to access Realplexor server.
require_once "Dklab/Realplexor.php";
$rpl = new Dklab_Realplexor("127.0.0.1", "10010", "demo_");
...
// Send data to channels. 
$rpl->send(array("Alpha", "Beta"), $_POST['message']);

Установка Realplexor-а


После скачивания dklab_realplexor.tar.gz его можно установить как автозапускаемый сервис Linux:
cd /opt
wget http://github.com/DmitryKoterov/dklab_realplexor/tarball/master
tar zxf *realplexor*.tar.gz
mv *realplexor*/ dklab_realplexor
 
# Now deal with an init-script.
ln -s /opt/dklab_realplexor/dklab_realplexor.init /etc/init.d/dklab_realplexor
chkconfig --add dklab_realplexor
chkconfig dklab_realplexor on
service dklab_realplexor start

Как мы используем Realplexor в РуТвите


Realtime-поиск и отслеживание онлайн-статуса канала. При просмотре результатов поиска твиты, удовлетворяющие запросу, появляются сверху в реальном времени (как в твиттер-поисках Google и Bing, а также в FriendFeed). Чтобы обеспечить этот функционал, сервер в каждый момент должен иметь информацию об «активных поисках», что обеспечивает соответствующая функция PHP API.

Подписка на канал. Когда вы смотрите на любую ленту твитов (свою, публичную и т. д. — по всему сайту), для нее используется канал Realplexor-а. Поэтому новый твит появляется у всех пользователей одновременно и без перезагрузки страницы.

Подписка на много каналов одновременно. В режиме просмотра а-ля FriendFeed, когда сообщения группируются в ветки, каждая ветка — это подписка на отдельный канал Realplexor-а (т.е. браузер подписан на десятки и иногда даже сотни каналов одновременно в одном соединении). Множественная подписка — это ключевой функционал Realplexor-а: через него реализованы, например, Like/Unlike (или ретвит), личные сообщения и т. д.

Отправка сообщения в несколько каналов сразу. Когда пользователь написал твит, сообщение отправляется одновременно в его персональный канал, во все home-каналы его друзей и в public-канал за один Realplexor-запрос.

Передача сообщений произвольной структуры. PHP-скрипт РуТвита формирует сообщения Realplexor-а в виде вложенных ассоциативных массивов, которые прозрачно преобразуются в JavaScript-объекты на стороне браузера.

Что дальше?


Описание API и примеры можно посмотреть на странице проекта. Приглашаю разработчиков к тестированию продукта. Я буду рад любым замечаниям или предложениям по улучшению Realplexor-а, а также форкам в GitHub и патчам в почте.

Официальная страница проекта
Tags: realtime real-time comet long-polling javascript perl libevent event loop производительность высоконагруженные проекты linux api rutvit рутвит
Hubs: High performance
+85
18.5k 251
Comments 141
Ads