Веб-разработка

индекс
236,88

Пуш ми, бум-бум, тач ми… Ajax Push Engine

logoСегодня поговорим о Comet и о server push вообще.

Обычные веб-приложения, как и сайты, работают по традиционной модели запрос-ответ-запрос, при этом, в силу особенностей HTTP-протокола и некоторых серверных реализаций обработчиков, приложение не хранит информацию между запросами, так что каждый вызов является независимым, а идентификация или сессионность обеспечиваются более высокоуровневыми средствами (например, всем известная реализация сессий в PHP). Кроме этого, запрос на новую информацию посылает всегда клиент, который заинтересован в получении самой актуальной версии данных. В приложениях, которым критично обновление, это часто становиться узким местом. У нас в одном из предыдущих проектов, было сразу несколько периодических AJAX-запросов на обновление данных. Хотя для такого случая есть варианты и вызова нескольких обработчиков на стороне сервера одним запросом от клиента.

ape-cross-browser1

Но существует другой подход, когда сервер самостоятельно определяет, что есть новые данные (а он то узнает об этом самым первым) и доставляет их клиентской программе, которая не тратит время на запросы, а сама получает, когда что-то новенькое появилось. Для этого, правда, необходимо держать постоянным подключение к серверу, например, через двунаправленный сокет. И если в традиционном ПО с этим особых сложностей не наблюдается, что реализовать долгие постоянные соединения для веб-приложений достаточно непросто. Самым примитивным способом это делают через IFrame, однако это не единственная возможность, да и разработчики топовых библиотек и плагинов к ним постарались, так что поищите в своем любимом фреймворке, реализация Comet там должна быть (она точно есть в Dojo Toolkit, есть плагины для jQuery, встроенная возможность в GWT). Также можете почитать о различных способах реализации вот в этом наборе материалов.

А вот как сделать сервер? Обычный вариант Apache + PHP слабо подходит, хотя, конечно, и на нем возможно, но решение будет далеко не оптимальным и не выдержит типичной нагрузки. Кстати, о нагрузке. Для Comet-приложений нагрузкой считается количество клиентов, которые могут быть обслужены одновременно, при этом имеется ввиду количество открытых соединений с клиентами, а не передача данных. И число таких соединений для обычных серверов должно достигать десятков тысяч, типичные цифры — 20 — 50 тыс. соединений параллельно. И вот тут связка Apache/PHP никак не поможет. Надо что-то другое.

Для мира Java есть реализации для серверов приложений, например, Jetty (наверное, самая известная и стандартная реализация Comet, вот хорошая статья на русском от IBM), не так давно появился серверный фреймворк на базе платформы GrizzleAtmosphere, так что реализовать собственную логику и свой сервер для специфического приложения не составит труда.

Остальным что делать? Им могу порекомендовать открытый проект APE или Ajax Push Engine. Это небольшой сервер, написанный на С, который компилируется в виде демона и слушает свой порт, по умолчанию, 6969, однако его можно настроить и на совместную работу с Apache. В отличие от других решений, APE это специализированный HTTP-сервер, который поддерживает GET/POST запросы, то есть, подключиться к серверу можно с любого языка и системы, лишь бы понимались HTTP-запросы. И это самодостаточно решение, в принципе, можно ограничится одним только APE, без дополнительных серверов (в Jetty реализация все же требует сервера приложений и веб-сервера). По заявлениям разработчиков, APE отлично работает под нагрузкой и способен держать одновременно до 100 тысяч соединений, в дальнейшем будет добавлена и горизонтальное масштабирование.

ape-how-it-works

Следует заметить, что по своей архитектуре, проект APE состоит из трех частей:
  • epoll-driven HTTP server — самая основа, сервер, который обрабатывает подключения и держит соединения, позволяя реализовать Server push любым подходящим для клиента образом, будь то XHR long-polling или через iframe, а в будущем и нативные возможности браузеров будут утилизированы (например, web sockets)
  • APE Javascript Framework — не менее важная часть проекта, клиентский скрипт на базе MooTools, который может интегрировать возможности сервера в любое клиентское AJAX-приложений. Также в нем реализована модульная система и расширения, так что поверх можно написать любую обертку для другой библиотеки или прозрачно встроить в ваше решение. Библиотека реализует имитацию сокетов и pipe, так что разработчик получает достаточно высокоуровневые абстракции, а если забраться еще выше, то ему доступна событийная модель и можно просто забыть о деталях реализации.
  • Система плагинов — сервер можно расширять, добавляя собственную функциональность через подключаемые модули. Сейчас доступно только через С-модули, однако они предельно просты, в будущем ожидается серверный Javascript, что станет по истине отличным решением (эх, ещё бы РНР туда прикрутить, хотя, конечно, можно через простенький C-плагин, но все же).

На стороне сервера, APE использует механизм epoll, а также реализацию хеш-таблицы (DJB Hash Algorithm). Это оборачивается, кроме максимальной производительности, ещё и сложностями в портировании — сервер хочет для сборки ядро Linux 2.6.19+ и libc6-dev, и пока заставить его собираться под Cygwin мне не получилось (стопор именно в плане epoll-механизма, встроенного в ядро).

Для обмена информацией между сервером и клиентом, а также между клиентами (через сервер), в APE реализовано несколько методов. Первый — каналы (Channels), когда пользователи подписываются на определенные каналы, а когда на сервере появляется новая информация, ассоциированная с этим каналом, она передается всем клиентам, слушающим канал. Таким образом можно сразу разослать новые данные всем клиентам, которых может быть неограниченное количество. Также APE можно использовать как очередь сообщений, хранимых в памяти — каждый подключенный пользователь имеет одну или несколько очередей. Получателем сообщения может быть или канал, тогда сообщение получат все, или напрямую другой пользователь, либо внешний сервис. Каналы могут быть как интерактивными, так и доступными только для чтения.

APE берет на себя роль прокси-сервера, позволяя обмениваться сообщениями с внешними сервисами (например, вашим сервером приложения), а также получать от них данные и рассылать их в каналы или конкретным пользователям. Таким образом, можно построить систему, в которой фронт-ендом для пользователей будет APE, который обрабатывает подключения, а дальше работает уже бек-енд сервер, поставляющий и принимающий данные в виде сообщений по внутреннему протоколу APE, однако ничего не знающий о количество подключенных клиентов, ему надо только уметь общаться с APE-сервером.

ape-communication-system

Взаимодействие между клиентом и сервером производится через специальный протокол. Пользователи могут инициировать команды, например, послать сообщение или создать подключение, в ответ на которые сервер шлет RAW-данные, обычно это JSON. Однако модули сервера могут расширять встроенный набор команд, поэтому вы можете описать собственный набор действий, в зависимости от потребностей.

Хотя официальная документация все еще в разработке (конечно, это вики), и не сообщает о доступных модулях, в репозитарии исходников доступны несколько базовых модуля, которые могут пригодится и как справочное пособие для разработки своих решений, так и для встраивания в уже существующую инфраструктуру. Например, libape-mysql позволяет подключаться к базе данных и получать оттуда новую информацию (однако, учтите, что версия модуля 0.01), а libape-chat покажет демо-версию простой чат-системы. Самым интересным обещает быть libape-spidermonkey, хотя пока о нем нет никакой информации, кроме исходника.

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

P.S. Если кому получится собрать этот сервер под Win32 систему — пожалуйста, поделитесь решением!
+35
29 мая 2009, 11:39
98

комментарии (34)

+2
Throwable #
В Http изначально не предусмотрен механизм callback. Поэтому единственное что приходится делать — это периодический полинг и по возможности задерживать ответ http настолько насколько это возможно, оставляя коннекшн открытым. Дело усложняют корпоративные proxy, которые имеют собственное представление о запросах, времени ожидания и т.д… Как показывает практика, сервисы типа google talk и icq по http из корпоративного окружения работают вон плохо. Наши прокси, например, закачивают response, прогоняют через корпоративный антивирь и после этого отдают клиенту. Понятно проблематично будет использовать http streaming.
0
vitali #
С развитием модели клиент-сервер должны развиваться и приложения которые вклиниваются между клиентом и сервером: proxy, фаерволы, антивирусы и т.д. Ну и конечно админы :-)
иначе будем стоять на месте
0
alekciy #
HTTP Streaming != Commet.

Как бэ так сложилось, что это немного разые понятия.
+2
kex #
Мне кажется, что самое просто решение для обратного вызова, это небольшой flash-апплет на клиенте.

Flash уже давно умеет работать с обычными сокетами, а так же взаимодействовать с JS в браузере, передавая ему событие и его данные. Почему бы не поручить ему эту часть работы.

На другой стороне может быть любой простейший socket-сервер.

–2
Prometheus #
Тихо так,
кажись, будущее настает, раз пошла речь о таких технологиях.
НЛО прилетело и опубликовало эту надпись здесь
–1
alek_sys #
Спросить о вы хотите чем-то?
0
alekciy #
То, что лично вам подобные вещи не нужны вовсе не значет, что «в вебе оно лишнее».
+1
animal #
Глянул через Firebug
Реализация проста — с начала работы скрипт «устанавливает сессию», после чего отправляет запрос на сервер. Ждёт одно из следующих событий:
1. Обрыв соединения
2. Получение данных

В любом из случаев он сразу повторно открывает соединение!
Во втором случае — ещё и совершает действие, основанное на полученных данных

Огромное спасибо за статью!
0
catlion #
Для Win32 есть дуплексные WCF-сервисы, правда, насколько я знаю, на стороне клиента там предполагается Silverlight, возможно я ошибаюсь.
–10
senyai #
[:|||||:]
+2
alekciy #
Лично я в подобной ситуации остановился на Erlang-е. Всем кому интересны подобные технологии рекомендую посмотреть и в эту сторону.
0
sirmakc #
Больше интересует как с этими вещами у flex и silverligth. Кто-нибудь решал такие задачи на этих технологиях?
+1
Geba #
Для flex посмотрите в сторону WebORB + RMTP (Real-time messaging)
НЛО прилетело и опубликовало эту надпись здесь
0
MzMz #
Я не совсем понял, кто-то тут еще писал про дуплексные сервисы — вы listeners-сокеты открываете на клиентской стороне? А как быть тем, кто за NAT сидит?
НЛО прилетело и опубликовало эту надпись здесь
+1
MzMz #
Вообще, у меня вот ADSL модем и я сижу за NAT, на всех работах локальные сети за NAT — опять же — всякие устройства и гаджеты в мобильных сетях… Сложно представить даже количество людей сидящих за NAT или хотя бы firewall'ами. Вы включенный стандартный firewall Windows учли?
НЛО прилетело и опубликовало эту надпись здесь
0
esc #
В среднем, согласно счетчикам, посетителей на сайтах в 1.3-1.5 раза больше, чем хостов.
НЛО прилетело и опубликовало эту надпись здесь
0
esc #
Кто такие вы?
Счетчики определяют. Не 100% точно (бывает что разными браузерами один человек пользуется или один браузер, но был реконнект в ходе которого был выдан новый ip), но это достаточно чтобы сказать, что на данный момент людей, что сидят за натом полно. Это и большие конторы и домосети и всякие студ. общаги где сотни и тысячи посетителей могут 1 или несколько ip использовать.
НЛО прилетело и опубликовало эту надпись здесь
0
esc #
Не знаю. Я говорю лишь о том, что nat пользователей достаточно много, чтобы их игнорировать. Ну конечно если идеолог проекта человек разумный…
0
SaveTheRbtz #
Ужс, неужто вы думаете что NAT пользователей лишь маленький процент?
Пускай, правда, что провайдеры дабы упростить себе жизнь начали выделять юзерам реальные айпишники, но как насчёт юзеров у которых дома Wi-Fi роутеры? Таких становится всё больше и больше.
0
MzMz #
И даже это далеко и ни разу не показатель.

Я сейчас сижу за ADSL-модемом. У меня внешний IP-адрес (пусть и динамический), внутри моей домашней подсети один компьютер. Я и посетитель и хост. Но к моему браузеру вы не пробьетесь пока я в модеме правила не настрою.

Я у скольких включен firewall под Windows — как creotiv собрался его включать? Неужели из набора секретных команд Javascript'а?
0
esc #
Если это мне, то пробьюсь, если куки включены. Ну в смысле посчитать смогу…
0
insa #
Зачем-то сделали свою обертку вокруг epoll и свой http парсер, вместо того, чтобы взять libevent.
0
SaveTheRbtz #
Alexey Ivanov a écrit:
> Will it be libevent or some custom implementation?

For the moment we don't plan to use libevent, but… who know :)
0
iAndrej #
Уже в двух проектах использовал DWR, очень хорошо вписывается в архитектуру J2EE. Против всяких прокси используется Early Closing Mode. Остался доволен.
0
VDG #
Если уж всё равно предлагается ставить ПО на сервер, то почему на костыли-то (HTTP)? Тогда уж полноценные сокеты открывать и на клиенте через флеш работать.

PS. сам делаю и на комете и на сокетах.
0
fuCtor #
Флеш не панацея, и чем больше различных технологий и подходов ИМХО тем лучше.
0
PingWin #
«Я как бэ не понял» (с), разве порт 6969 не является де-факто портом BitTorrent-трекеров? Или с появлением php'шных трекеров их вешают только на 80-ый порт? :)
0
SaveTheRbtz #
Пообщался с автором по поводу поддержки не-линукс систем, если кому интересно:
Alexey Ivanov a écrit:
> > Are you planing to add support for non-epoll systems like FreeBSD and
> > Solaris by using kqueue and /dev/poll on that OSes?
> >
> > —
> > Sincerely y0uRz,
> > Alexey Ivanov

Hi Alexey,

Since kqueue et /dev/poll work on the same way than epoll, porting APE
to such OS could be pretty easy.
This will may be happen on the 1.0 release ;)

Cheer,

Anthony Catel

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