
Принцип “Long Polling” (или “Comet“) позволяет сделать возможным установление постоянного соединения клиента с Web приложением и также периодичной отправки данных клиенту в рамках этого соединения (без необходимости клиента постоянно делать HTTP запросы для проверки новых данных). Другими словами, эта модель позволяет реализовать постоянные HTTP соединения для получения данных порциями. Наиболее популярное применение — чаты, твиттеры и другие live-updated потоки — клиент постоянно “слушает” сервер на предмет появления новых сообщений, и как только новые сообщения появляются — они мгновенно доставляются ему.
Сам принцип не несет в себе инноваций в HTTP протоколе, т.к. этот подход реализуем обычными средствами. Проблема заключается в том, что стандартное решение — установка постоянного соединения с обычным Web сервером (а значит и с обслуживающей платформой, например php-бекендом) — крайне ресурсоемкое и не применимо на практике. Другой подход — постоянно опрашивать приложение на предмет появления новых данных является еще более ресурсоемким.
Решением этой проблеммы стали т.н. HTTP-PUSH (или comet) сервера, позволяющие облуживать огромное количество постоянных соединений эффективно расходуя ресурсы. Как они устроены и как применяются на практике?
Принцип работы Comet-сервера
Необходимо отметить, что Comet сервер решает задачу отправки клиенту определенных данных порциями. Comet сервера реализуют т.н. HTTP Push Relay протокол (например, ). Принцип работы такого протокола заключается в следующем:
- На Web сервере создается т.н. “канал” с уникальным ключем. Это делается на стороне приложения путем посылки запроса к Comet-серверу
- Клиент устанавливает обычное HTTP соединение с Comet-сервером, передавая в параметры ключ канала, из которого он будет получать данные. Сервер удерживает такое соединение, пока не отправит очередную порцию данных
- Основное приложение, по определенному событию (например, кто-то написал сообщение клиенту), шлет в канал Comet сервера с нужным ключем это сообщение
- Как только в канале появляется сообщение, Comet сервер отправляет его соответствующему клиенту и закрывает HTTP соединение (иногда соединения не закрываются, а продолжают быть активными)
Таким образом, сервер реализует “стэки” сообещений, а их раздача происходит без участия тяжелых бекендов. Бекенды вступают в силу только тогда, когда необходимо отправить сообщение.
Nginx и модуль HTTP Push
Модуль nginx_http_push_module позволяет превратить в Comet сервер, реализуя протокол Basic HTTP Push Relay Protocol. Преимущества этого модуля и протокола — в его простоте по сравнению с альтернативными решениями (например, протоколом и сервером CometD).
Установка
Для установки модуля необходимо скачать его исходники и перекомпилировать , т.к. модуль является внешней разработкой:
wget http://pushmodule.slact.net/downloads/nginx_http_push_module-0.692.tar.gz
tar -xvf nginx_http_push_module-0.692.tar.gz
...
cd /where//sources/are
./configure \
--add-module=/path/to//modules/sources/nginx_http_push_module-0.692/
make; make install
Конфигурация
Для базовой конфигурации нам необходимо объявить две рабочих точки в ’e: точка публикации сообщений (приватная — доступна только для самого приложения) и точка раздачи сообщений (публичная — к которой будут подключаться клиенты):
location /publish {
# Название переменной с идентификатором канала
# в нашем примере "cid", т.е. запрос будет таким:
# http://example.com/publish?cid=s42378fwe
set $push_channel_id $arg_cid;
push_publisher;
# Отключаем хранение очереди (сообщение удаляется после доставки)
push_store_messages off;
}
location /listen {
push_subscriber;
# Обслуживать только первого "слушателя"
# Остальным отправляем 403
push_subscriber_concurrency first;
# Идентификатор канала
set $push_channel_id $arg_cid;
# Тип ответа
default_type text/plain;
}
После этого при отправке сообщения нужно будет посылать его в соотв. канал, делая POST запрос на “/publish”. Клиент же отправляет GET запрос на “/listen” и ждет ответа. Когда приходит ответ, клиент делает повторный запрос на “/listen” и т.д.
Все параметры конфигурации с подробным описанием смотрите на .
Пример
В качестве примера ниже приведен код на PHP, который используется для отправки сообщения в канал:
# Определяем ID канала
$channel_id = 12345;
# Сообщение
$message = 'Привет тебе!';
# Отправляем сообщение в канал
$c = curl_init( 'http://localhost/publish?cid=' . $channel_id );
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_POSTFIELDS, json_encode($message));
$r = curl_exec($c);
Для получения сообщения код на Javascript будет выглядеть где-то так (на основе ):
var channelId = 12345;
function check_messages() {
$.get('/listen?cid=' + channelId, {}, function(r) {
// Считаем, что у нас есть div c id=messages,
// куда мы дописываем сообщения
$('#messages').append(r);
setTimeout(check_messages, 500);
}, 'json');
}
check_messages();
В каких случаях Вам приходилось пользоваться comet-серверами?
Related posts:
Комментариев нет:
Отправить комментарий