Reverse Ajax: Часть 4. Atmosphere и CometD

Как использовать лучшие библиотеки Reverse Ajax с открытым исходным кодом для Java-серверов

В этом цикле статей говорится о том, как разработать событийно-управляемое Web-приложение с использованием методов Reverse Ajax. В первой части приведены различные способы реализации связи Reverse Ajax. В части 2 объясняется, как реализовать Reverse Ajax, используя WebSockets, и обсуждаются ограничения для Web-серверов с применением Comet и WebSockets. Часть 3 посвящена трудностям реализации системы связи Comet или WebSockets, если нужна поддержка нескольких серверов или нужно создать независимое Web-приложение, которое пользователи могут разместить на своем сервере. В ней также описана библиотека Socket.IO. Из настоящей статьи вы узнаете об Atmosphere и CometD - самых популярных библиотеках Reverse Ajax с открытым исходным кодом для Java-серверов.

Матье Карбу, Java Web-архитектор, Ovea

Фото Матье КарбуМатье Карбу (Mathieu Carbou), Java Web-архитектор и консультант компании Ovea, предоставляет услуги и разрабатывает решения. Он коммиттер и руководитель нескольких проектов по разработке ПО с открытым исходным кодом, докладчик и глава монреальской группы пользователей Java. Матье обладает богатым практическим опытом программирования и специализируется на разработке событийно-управляемых Web-программ для клиентских и серверных систем, а также на решениях для высокомасштабируемых Web-приложений, управляемых событиями и сообщениями. Познакомьтесь с его блогом.



17.08.2012

Введение

В этом цикле статей показано, как разработать событийно-управляемое Web-приложение с использованием методов Reverse Ajax. Часть 1 знакомит читателя с методами Reverse Ajax - опросами, потоками, Comet и ждущим опросом. В части 2 объясняется, как реализовать Reverse Ajax, используя WebSockets, и обсуждаются ограничения для Web-серверов с применением Comet и WebSockets. Часть 3 посвящена трудностям реализации системы связи Comet или WebSockets, если нужна поддержка нескольких серверов или нужно создать независимое Web-приложение, которое пользователи могут разместить на своем сервере. Даже если код JavaScript на стороне клиента простой, вам потребуются средства обработки исключений, восстановления соединения и подтверждения соединения. На стороне сервера отсутствие общего API и многообразие API для Web-серверов приводит к необходимости создания инфраструктуры, которая обеспечит абстрагирование. В части 3 также обсуждается Socket.IO.

Из настоящей статьи вы узнаете об Atmosphere и CometD. Это наиболее популярные библиотеки Reverse Ajax с открытым исходным кодом для Java-серверов.

Загрузите исходный код примеров для этой статьи.

Предварительные требования

Чтобы извлечь максимальную пользу из этой статьи, в идеале нужно знать JavaScript и Java. Для запуска примера из этой статьи понадобится также последняя версия Maven и JDK (см. раздел Ресурсы).


Инфраструктура Atmosphere

Atmosphere – это Java-инфраструктура, которая предоставляет общий API для использования функций Comet и WebSocket на многих Web-серверах, включая Tomcat, Jetty, GlassFish, WebLogic, Grizzly, JBossWeb, JBoss и Resin. Поддерживаются также любые Web-серверы, соответствующие спецификации Servlet 3.0. Atmosphere поддерживает больше всего серверов среди всех инфраструктур, представленных в статьях этого цикла.

Atmosphere может обнаруживать зависящие от платформы API сервера (Comet и WebSockets) и в случае Comet возвращаться к Servlet 3.0, если он есть. В другом варианте, также в случае Comet, она возвращается в "управляемый" асинхронный режим (но не столь масштабируемый, как Jetty Continuations). Atmosphere существует уже более двух лет и все еще находится в стадии активной разработки. Она используется в крупных Web-приложениях, например, JIRA, одной из наиболее известных систем отслеживания проблем. На рисунке 1 показана архитектура Atmosphere.

Рисунок 1. Архитектура Atmosphere
Архитектура Atmosphere

Содержащаяся в Atmosphere инфраструктура исполнения обеспечивает общий интерфейс для всех решений и стандартов Web-серверов. Помимо этого, путем создания простого сервлета можно обеспечить доступ клиента через Google Web Toolkit (GWT) к API и функциям Reverse Ajax. Можно также использовать Jersey - инфраструктуру, реализующую JSR-311 (спецификацию JAX-RS). Таким образом, Atmosphere можно использовать в RESTful-сервисах с предоставлением дополнительных аннотаций. Настроив выбранный модуль, можно получить доступ к инфраструктуре исполнения Atmosphere путем реализации некоторых классов (см. ниже). Также можно использовать некоторые готовые плагины, которые добавляют поддержку кластеров, обмена сообщениями, внедрения зависимостей и многое другое. Если используется Web-инфраструктура (Wicket, Struts, Spring MVC), поддержку Reverse Ajax можно добавить прозрачно с помощью сервлета Atmosphere MeteorServlet. Этот сервлет предоставляет объект Meteor, к которому можно обращаться из имеющихся контроллеров и сервисов для приостановки или возобновления запросов.

Вся мощь Atmosphere остается на стороне сервера: она обеспечивает стандартизированный API, который охватывает всевозможные решения и способы связи с WebSockets или Comet. Atmosphere не использует протокол связи между клиентом и сервером, как Socket.IO и CometD. Обе библиотеки предоставляют клиентский код JavaScript и сервлет для сервера, которые взаимодействуют с помощью специального протокола (рукопожатия, обмена сообщениями, подтверждения связи или мониторинга состояния). Задача Atmosphere ― обеспечить общий канал связи со стороны сервера. Если нужно использовать определенный протокол, например, Bayeux (протокол, используемый CometD), вам придется разработать свой собственный "обработчик" для Atmosphere. Плагин CometD и есть такой обработчик: он использует API Atmosphere для приостановки и возобновления запросов и делегирует CometD классы для управления CometD-связью с использованием протокола Bayeux.

Для облегчения настройки соединения Atmosphere поставляется с клиентской библиотекой JQuery, которая может автоматически определять наилучший из имеющихся в наличии транспортов (WebSockets или CometD). Использование плагина JQuery из Atmosphere аналогично API WebSockets из HTML5. Вы подключаетесь к серверу, регистрируете обратный вызов для получения сообщений - и можете передавать те или иные данные.

Исходный код для этой статьи содержит образец Atmosphere, в котором обработчик непосредственно используется с сервлетом Atmosphere. Клиентский код всегда одинаков, это тот же код, который используется в статьях 1, 2 и 3 этого цикла (в примерах чата с применением ждущего опроса Comet). Можно использовать плагин JQuery из Atmosphere, но это не обязательно, потому что Atmosphere не принуждает следовать какому-то определенному протоколу связи. Мы настоятельно советуем посмотреть другие примеры из проекта Atmosphere, особенно с использованием аннотаций JSR-311 (Jersey). Они действительно упрощают написание обработчиков.

В листинге 1 показан интерфейс обработчика Atmosphere.

Листинг 1. Интерфейс AtmosphereHandler
public interface AtmosphereHandler<F, G> { 
    void onRequest(AtmosphereResource<F, G> resource) 
        throws IOException; 
    void onStateChange(AtmosphereResourceEvent<F, G> event) 
        throws IOException; 
    void destroy(); 
}

В листинге 2 показана реализация метода onRequest для чата Comet.

Листинг 2. Интерфейс AtmosphereHandler - onRequest
Broadcaster broadcaster = 
        BroadcasterFactory.getDefault().lookup(
        DefaultBroadcaster.class, ChatHandler.class.getName(), true); 
broadcaster.setScope(Broadcaster.SCOPE.APPLICATION); 
resource.setBroadcaster(broadcaster); 
HttpServletRequest req = resource.getRequest(); 
String user = (String) req.getSession().getAttribute("user"); 
if (user != null) { 
    if ("GET".equals(req.getMethod())) { 
        resource.suspend(-1, false); 
    } else if ("POST".equals(req.getMethod())) { 
        String cmd = req.getParameter("cmd"); 
        String message = req.getParameter("message"); 
        if ("disconnect".equals(cmd)) { 
            close(resource); 
        } else if (message != null && message.trim().length() > 0) {
            broadcaster.broadcast("[" + user + "] " + message); 
        } 
    } 
}

Типовое соглашение заключается в том, чтобы приостанавливать GET-запросы и отправлять сообщения с помощью POST-запросов. Когда сообщение получено, оно транслируется для всех ресурсов, зарегистрированных в трансляторе. Обратите внимание, что пример никогда ничего не пишет в выходной поток HttpServlet. Действие трансляции или приостановки лишь пересылает события, полученные с помощью другой реализацией метода, как показано в листинге 3.

Листинг 3. Интерфейс AtmosphereHandler - onStateChange
Broadcaster broadcaster = 
    BroadcasterFactory.getDefault().lookup(
        DefaultBroadcaster.class, ChatHandler.class.getName(), true); 
// Клиент закрыл соединение. 
if (event.isCancelled()) { 
    close(event.getResource()); 
    return; 
} 
try { 
    String message = (String) event.getMessage(); 
    if (message != null) { 
        PrintWriter writer = 
            event.getResource().getResponse().getWriter(); 
        writer.write(message); 
        writer.flush(); 
    } 
} finally { 
    if (!event.isResumedOnTimeout()) { 
        event.getResource().resume(); 
    } 
}

Теперь у вас есть все необходимое для работы Comet-чата. Итак, по поводу Atmosphere важно помнить следующее: объект ресурса, представляющего соединение, и ретранслятор несут ответственность за трансляцию событий ресурсам и выбор времени приостановки или возобновления запроса. Имейте в виду, что приведенный пример относится только к Comet. Чтобы иметь возможность использовать WebSockets и Comet, нужно использовать клиентскую библиотеку, и потребуется более сложный обработчик.

В таблице 1 приводятся плюсы и минусы использования инфраструктуры Atmosphere.

Таблица 1. Достоинства и недостатки Atmosphere
ДостоинстваНедостатки

Если нужно развернуть Web-приложение на нескольких Web-серверах, которые вы не контролируете, у вас будет больше шансов, что функции Reverse Ajax вашего приложения будут работать корректно благодаря поддержке инфраструктурой Atmosphere большого количества Web-серверов.

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

Отсутствие документации по архитектуре Atmosphere, проекту, концепциям и API, которая была бы полезной в тех случаях, когда нужно обратиться к исходному коду или проанализировать предоставленные примеры. API слишком формален и иногда и недостаточно ясен по сравнению с простыми API других инфраструктур, таких как Socket.IO и CometD. Даже при наличии аннотаций Atmosphere некоторые имена и атрибуты слишком формальны.

Несмотря на отличную абстракцию со стороны сервера, недостает хорошей клиентской библиотеки. Протокол отсутствует, так что создание всех дополнительных возможностей возлагается на разработчиков. В настоящее время библиотека слишком проста для нужд больших, масштабируемых Web-приложений, когда требуется развитые средства определения тайм-аута, подтверждения связи, отката, кросс-доменного взаимодействия и т.п., особенно при работе с мобильными устройствами. В этом случае CometD гораздо надежнее, он обеспечивает протокол связи, который можно использовать для управления потоками и обнаружения ошибок. Если нужны дополнительные возможности, хорошей альтернативой может быть использование JavaScript-клиента CometD с помощью плагина Atmosphere CometD.


Инфраструктура СometD

Инфраструктура CometD, управляемое событиями коммуникационное решение на основе HTTP, существует уже несколько лет. В версии 2 добавлена поддержка настройки аннотаций и WebSockets. Инфраструктура CometD обеспечивает серверную и клиентскую части на Java, а также клиентские библиотеки JavaScript, основанные на JQuery и Dojo. CometD использует стандартный протокол Bayeux, что позволяет активировать некоторые расширения для подтверждения сообщений, управления потоками, синхронизации, кластеризации и т.п.

Событийно-ориентированный подход, принятый в CometD, очень хорошо вписывается в новую концепцию Web-разработки, управляемой событиями. Как и в традиционных пользовательских интерфейсах, все компоненты сообщаются через канал связи для отправки уведомлений и приема событий. Все сообщения асинхронны.

Инфраструктура СometD:

  • хорошо документирована;
  • содержит образцы и архетипы Maven для облегчения запуска проекта;
  • имеет хорошо продуманный API, который позволяет разрабатывать расширения;
  • содержит модуль кластеризации Oort, который предоставляет возможность работать с несколькими Web-серверами CometD в качестве узлов кластера с выравниванием нагрузки для масштабирования с целью обеспечения большого числа HTTP-соединений;
  • поддерживает политики безопасности, позволяя точно выбирать каналы для каждого отправителя сообщений;
  • хорошо сочетается со инфраструктурами внедрения зависимостей Spring и Google Guice.

Протокол Bayeux

Протокол связи Bayeux работает главным образом через HTTP. Он обеспечивает асинхронную реактивную двунаправленную связь между клиентом и сервером. Протокол Bayeux основан на каналах, по которым сообщения направляются и доставляются от клиента на сервер, от сервера к клиенту или от одного клиента к другому (но не через сервер). Bayeux – это протокол типа "публикация-подписка". CometD реализует протокол Bayeux и таким образом обеспечивает уровень абстракции поверх транспортов Comet и WebSocket для маршрутизации запросов через Bayeux.

Серверы и внутренние механизмы

CometD комплектуется тремя транспортами: JSON, JSONP и WebSocket. Они зависят от API Jetty Continuations и Jetty WebSocket. По умолчанию CometD может использоваться в Jetty 6, 7 и 8, а также любых других серверах, поддерживающих спецификацию Servlet 3.0. Транспорты можно добавлять и разрабатывать так же, как и расширения. Нужно писать транспорты, поддерживающие API Grizzly WebSocket и др., а затем добавлять их на этапе настройки сервера CometD. На рисунке 2 приведен обзор основных блоков CometD.

Рисунок 2. Архитектура CometD
Архитектура CometD CometD поддерживает расширения и различные уровни транспорта (WebSockets, ждущий опрос Ajax и др.), а также несколько API на стороне сервера.

Уровень безопасности для доступа к каналам сообщений на рисунке 2 не показан.

В исходном коде примеров для этой статьи содержится Web-приложение с применением CometD. Дескриптор Web-приложения в листинге 4 содержит определение для примера чата.

Листинг 4. web.xml
<servlet> 
    <servlet-name>cometd</servlet-name> 
    <servlet-class>
        org.cometd.java.annotation.AnnotationCometdServlet
    </servlet-class> 
    <async-supported>true</async-supported> 
    [...]
    <init-param> 
        <param-name>services</param-name> 
        <param-value>ChatService</param-value> 
    </init-param> 
    <init-param> 
        <param-name>transports</param-name> 
        <param-value>
            com.ovea.cometd.websocket.jetty8.Jetty8WebSocketTransport
        </param-value> 
    </init-param> 
</servlet>

Сервлет CometD поддерживает несколько вариантов параметров настройки глобального управления, в частности, возможность выбирать транспорты и сервисы. В примере предполагается, что нужно добавить поддержку WebSocket Jetty 8. Класс сервиса CometD ChatService на стороне сервера управляет чат-румом, где каждый может говорить, как показано в листинге 5.

Листинг 5. Класс ChatServiceCometD
@Service 
public final class ChatService { 

    @Inject 
    BayeuxServer server; 

    @PostConstruct 
    void init() { 
        server.addListener(new BayeuxServer.SessionListener() { 
            @Override 
            public void sessionAdded(ServerSession session) { 
                [...]
            } 

            @Override 
            public void sessionRemoved(ServerSession session, boolean timedout) {
                [...]
            } 
        }); 
    } 

    @Configure("/**") 
    void any(ConfigurableServerChannel channel) { 
        channel.addAuthorizer(GrantAuthorizer.GRANT_NONE); 
    } 

    @Configure("/chatroom") 
    void configure(ConfigurableServerChannel channel) { 
        channel.addAuthorizer(new Authorizer() { 
            @Override 
            public Result authorize(
                [..] // check that the user is in session
            } 
        }); 
    } 

    @Listener("/chatroom") 
    void appendUser(ServerSession remote, 
                    ServerMessage.Mutable message) { 
        [...]
    } 

}

Листинг 5 демонстрирует некоторые важные особенности CometD, в том числе:

  • внедрение зависимостей;
  • управление жизненным циклом;
  • глобальную настройку каналов;
  • управление защитой;
  • преобразование сообщений (для добавления имени пользователя перед всеми сообщениями);
  • управление сеансами.

На стороне клиента пример не активирует никаких расширений - только собственный код CometD, как показано в листинге 6.

Листинг 6. Клиентский код CometD
// Сначала создаем объект t cometd и настраиваем его

var cometd = new $.Cometd('CometD chat client'); 
cometd.configure({ 
    url: document.location + 'cometd', 
    logLevel: 'debug' 
}); 
cometd.websocketEnabled = 'WebSocket' in window;

// Затем регистрируем некоторые обработчики событий. Метаканалы (в 
// в форме /meta/<name>) – это специально зарезервированные каналы)

cometd.addListener('/meta/disconnect', function(message) { 
    [...]
}); 

cometd.addListener('/meta/connect', function(message) { 
    [...]
});

// Затем можно установить соединение:

cometd.handshake();

// И  подписки: 

cometd.subscribe('/chatroom', function(event) { 
    [...] //  event.data holds the message
});

// Наконец, мы отправляем данные в чат-рум:

cometd.publish('/chatroom', msg);

Клиентский API CometD прост для использования и понимания, но при этом является мощным и расширяемым. Эта статья охватывает только основные части Web-приложения, и чтобы получить лучшее представление о возможностях CometD, обратитесь к примеру приложения.

В таблице 2 приводятся плюсы и минусы использования инфраструктуры CometD.

Таблица 2. Достоинства и недостатки CometD
ДостоинстваНедостатки

CometD предлагает комплексное решение от клиента к серверу, а также от автономного Java-клиента к серверу. Инфраструктура хорошо документирована, имеет хороший API и проста в применении. Лучше всего то, что в ней принят событийно-ориентированный подход. CometD и Bayeux входят в состав многих событийно-управляемых Web-приложений. Другие инфраструктуры Reverse Ajax не предоставляют событийно-управляемых механизмов, вынуждая конечных пользователей разрабатывать свое собственное нестандартное решение.

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

В настоящее время CometD не поддерживает никаких контейнеров Servlet 2.5, кроме Jetty для Comet (Tomcat), и не поддерживает Glassfish/Grizzly WebSocket.


Заключение

Atmosphere и CometD ― это мощные решения Reverse Ajax с открытым исходным кодом. В компании Ovea мы выбрали CometD, потому что разрабатываем масштабируемые событийно-управляемые Web-приложения для мобильных устройств в кластерной инфраструктуре и получаем полный контроль над инфраструктурой (мы используем Jetty). Но CometD без дополнительной разработки может оказаться не лучшим выбором, если вы продаете Web-приложения и хотите, чтобы функции Reverse Ajax работали на как можно большем количестве серверов. Однако учитывая, что все больше и больше Web-контейнеров поддерживает Servlet Specification 3.0, инфраструктура CometD становится все менее ограниченной. Что касается транспортного уровня, то здесь основное различие между двумя инфраструктурами заключается в поддержке WebSocket.


Загрузка

ОписаниеИмяРазмер
Исходный код примера для статьиreverse_ajaxpt4_source.zip28 КБ

Ресурсы

Научиться

Получить продукты и технологии

  • Исходный код Atmosphere: Atmoshphere, инфраструктура на базе POJO с использованием шаблона Inversion of Control (IoC), делающая возможности Comet и WebSocket доступными широким массам разработчиков.
  • Исходный код CometD: проект, который представляет собой масштабируемую реализацию Web-сообщений comet (server push).
  • Расширения CometD: расширения для поддержки Jetty 8 WebSocket и Google Guice от Ovea.
  • Jetty: Jetty, Web-сервер и контейнер javax.servlet с поддержкой WebSockets.
  • Документация Apache Tomcat Advanced I/O: полезные ссылки, руководство пользователя, справочник и инструкции по разработке для Apache Tomcat.
  • Grizzly NIO Framework: воспользуйтесь преимуществами API Java NIO.
  • Пример Comet для Grizzly: изменения, которые нужно внести в существующие приложения, чтобы не создавать новые с нуля.
  • Сервер приложений GlassFish: основной пакет GlassFish Server Open Source Edition.
  • Socket.IO Java: оригинальный проект и самый последний вариант от Ovea.
  • Apache Maven: инструмент для управления проектами разработки программного обеспечения.

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура, SOA и web-сервисы
ArticleID=830886
ArticleTitle=Reverse Ajax: Часть 4. Atmosphere и CometD
publish-date=08172012