Java EE в мире Web 2.0

Внедрение асинхронных, основанных на обработке событий архитектур как ответ на запросы современных Web-приложений

Производительность и масштабируемость приложений Web 2.0, разработанных на основе стандартных решений Java™Platform, Enterprise Edition 5 (Java EE), далеки от идеала. Во многом это обусловлено тем, что основные архитектурные принципы платформы Java EE, в особенности использование синхронных API, идут вразрез с требованиями Web 2.0. В данной статье мы объясним противоречия между принципами Java EE и Web 2.0, расскажем о преимуществах асинхронных API и рассмотрим некоторые из возможных решений для разработки асинхронных Web-приложений на Java.

Константин Плотников, главный инженер, Axmor

Константин Плотников (Constantine Plotnikov) является ведущим инженером в компании Axmor Software и в команде IBM Customer Innovation Team (CIT) Lab в Новосибирске, Россия. Он получил степень магистра математики в Новосибирском государственном университете. Константин работает в области распределенных приложений c 1994 г. и обладает более чем 15-летним опытом работы в ИТ-индустрии. Он был членом экспертных групп Java Data Objects (JDO) и Java Metadata Interface (JMI) в организации Java Community Process.



Артем Папков, проектировщик решений, IBM

Артем Папков (Artem Papkov) на данный момент работает проектировщиком решений в команде IBM Client Innovation Team, которая ведет работу с клиентами и партнерами по внедрению новейших технологий, таких как SOA и Web-сервисы. После окончания Белорусского Государственного Университета Информатики и Радиоэлектроники в 1998 со степенью магистра в области компьютерных наук он поступил в 200 году на работу в IBM, в Research Triangle Park, NC. Артем имеет опыт в разработке многоуровневых решений с использованием новейших технологий, в проектировании и интеграции решений, основаных на интернет-технологиях. Последние три года он работает с клиентами и помогает внедрять Web-сервисы (которые являются стратегической интеграционной технологией IBM) и SOA (интеграционный подход).



Джим Смит, менеджер, IBM

Джим Смит (Jim Smith) имеет более 18 лет опыта в области разработки программного обеспечения. Его карьера началась в Sandia National Labs в Ливерморе, штат Калифорния, с конструирования высокоскоростных систем сбора данных и распределенных компьютерных систем, использующих огромное количество унаследованного кода. Обладая глубоким знанием языка Java и хорошими навыками общения с клиентами, Джим перешел в команду Emerging Internet Technologies, которая занимается реализацией Java-решений для клиентов IBM. Джим является одним из основателей Advanced Technology Solutions (ATS), всемирной организации по разработке и предоставлению услуг в области программного обеспечения, миссией которой является разработка, улучшение и франчайзинг передовых технологий и легковесных бизнес-процессов для IBM, лабораторий разработок, партнеров по бизнесу и клиентов. Результатом деятельности организации является более быстрая адоптация и развертывание стандартных технологий и продуктов IBM. На сегодняшний день Джим руководит этой организацией.



25.08.2008

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

Принципы и предположения, лежащие в основе Java EE

Платформа Java EE создавалась в расчете на разработку приложений типа “предприятие-покупатель” (business-to-consumer – B2C) и “предприятие-предприятие” (business-to-business – B2B). В какой-то момент предприятия открыли для себя возможности Интернета и начали использовать их для развития существующих бизнес-отношений со своими партнерами и клиентами. Эти интернет-приложения зачастую работали в связке с ранее созданными системами для корпоративной интеграции (enterprise integration system – EIS). Этот акцент на BCB, B2B и EIC-приложения нашел свое отражение и в наиболее популярных тестах, таких как ECperf 1.1, SPECjbb2005 и SPECjAppServer2004 (см. Ресурсы), предназначенных для измерения производительности и масштабируемости Java EE-серверов. Даже стандартный пример приложения на Java – PetStore является ничем иным, как приложением для электронной коммерции.

В тестах также отражено множество явных и подразумеваемых предположений насчет масштабируемости архитектуры Java EE:

  • С клиентской точки зрения, наиболее важной характеристикой, влияющей на производительность, является пропускная способность.
  • Главным фактором, определяющим производительность, является длина транзакции, поэтому работу приложения можно ускорить, сократив продолжительность каждой транзакции.
  • Транзакции в основном изолированы друг от друга.
  • В большинстве транзакций, за исключением длительных, изменяется состояние небольшого числа объектов.
  • Продолжительность транзакций ограничивается производительностью сервера приложений и систем EIS, работающих в том же административном домене.
  • Затраты на передачу информации по сети (в случае обращения к локальным ресурсам) компенсируются преимуществами использования пулов соединений.
  • Продолжительность транзакций может быть снижена путем оптимизации конфигурации сети и инвестиций в сетевое аппаратное и программное обеспечение.
  • Управление данными и контентом находится полностью в ведении приложения. При отсутствии каких-либо зависимостей от внешних сервисов основным фактором, ограничивающим передачу контента потребителю, является пропускная способность канала передачи данных.

Проблемы, связанные с производительностью и масштабируемостью

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

В настоящее время появляется множество новых решений и технологий, таких как пиринговые (peer-to-peer) и сервис-ориентированные (SOA) архитектуры, а также новые типы Web-приложений, получившие неофициальное название Web 2.0, которые не вписываются в рамки, установленные Java EE. В частности, им приходится иметь дело с длительными транзакциями. Поэтому использование традиционных подходов и принципов Java EE при разработке приложений Web 2.0 влечет за собой серьезные проблемы, связанные с производительностью и масштабируемостью.

Эти предположения породили нижеперечисленные принципы, которые стали основой для разработки Java EE API:

  • Синхронные интерфейсы приложений (API). В большинстве случае в Java EE используются синхронные API за исключением, пожалуй, только тяжеловесного и неудобного в использовании сервиса сообщений JMS (Java Message Service). Требование синхронности продиктовано скорее соображениями удобства, чем производительности. Синхронные интерфейсы легче в использовании и легче оптимизируются. Неограниченный потоковый параллелизм может быстро привести к серьезным проблемам, поэтому его использование при разработке приложений Java EE крайне не рекомендуется.
  • Ограниченные пулы потоков. Достаточно быстро выяснилось, что потоки являются весьма важным типом ресурсов, и производительность серверов приложений резко ухудшается, если количество потоков превышает определенное пороговое значение. Однако, принимая во внимание предположение, что все операции должны выполняться за короткое время, их можно распределить между небольшим числом потоков для сохранения высокой пропускной способности обработки запросов.
  • Ограниченные пулы соединений. Сложно достичь оптимальной производительности при работе с базой данных, используя единственное соединение. Разумеется, некоторые операции могут выполняться параллельно, но увеличение числа соединений улучшает производительность только до определенного предела, после которого открытие дальнейших соединений приводит к существенному падению скорости работы. Зачастую число соединений с базой данных меньше числа доступных потоков в пуле сервлета. Поэтому используются также пулы соединений, благодаря которым серверные компоненты, такие как сервлеты или объекты EJB (Enterprise JavaBean), могут получать соединения и возвращать их в пул после использования. Если доступных соединений нет, компонент переходит в режим ожидания, блокируя выполнение потока. Эта задержка обычно невелика, поскольку все остальные компоненты быстро возвращают соединения в пул.
  • Фиксированные соединения с ресурсами. Предполагается, что приложения должны использовать небольшое количество внешних ресурсов, получая к ним доступ через фабрику соединений, ссылка на которую, в свою очередь, может быть получена с помощью интерфейса JNDI (Java Naming and Directory Interface) или механизма инъекции зависимостей (dependency injection) в EJB 3.0. Фактически единственным серьезным программным интерфейсом Java EE, поддерживающим возможность подключения к ресурсам различных EIS, является API корпоративных Web-сервисов (см. Ресурсы). Остальные интерфейсы, как правило, работают только с заранее определенным списком ресурсов, и считается, что для открытия соединений с ресурсами требуются только параметры доступа (мандат пользователя).

Все эти принципы прекрасно работали для приложений Web 1.0 и позволяли разрабатывать множество замечательных приложений. Но при этом принципы Java EE оказываются неэффективными в эпоху Web 2.0.


Web 2.0: картина меняется

Java EE и появление SOA

Появление архитектуры SOA стало одним из первых вызовов, брошенных платформе Java EE. В SOA взаимодействие между различными компонентами может сочетать высокую пропускную способность с возможностью больших задержек, обусловленной обращениями к внешним сервисам через несколько доменов. Более того, некоторые взаимодействия могут потребовать утверждения пользователями, что вносит задержки продолжительностью от нескольких часов до недель. Наконец, SOA предполагает возможность использования различных посредников при обработке запросов, что только обостряет проблему латентности.

Одним из вариантов решения данной проблемы на Java EE стало использование интерфейсов для организации транзакционных сообщений, а также внедрение понятия бизнес-процесса. В то же время существуют определенные противоречия между вызовами Web-сервисов по принципу SOAP-через-HTTP и сервисами сообщений, например, JMS. HTTP работает по синхронной модели типа запрос/ответ и не предоставляет никаких возможностей для обеспечения надежности. Для разрешения подобных противоречий при использовании Web-сервисов в приложениях B2C были разработаны спецификации WS-Notification, WS-Reliability, WS-ReliableMessaging и WS-ASAP. Однако в B2C-системах чаще используются “толстые” клиенты, потому что они, в отличие от Web-приложений, могут эффективно бороться с проблемой высокой латентности, используя специфические для каждого сценария модели взаимодействия с пользователем.

Приложения Web 2.0 выдвигают множество требований, затрудняющих их реализацию на платформе Java EE. В частности, Web 2.0-приложения взаимодействуют между собой через различные сервисные интерфейсы значительно интенсивнее, чем в случае Web 1.0. Еще более серьезным отличительным признаком является поддержка операций типа “потребитель-потребитель” (consumer-to-consumer или C2C). Другими словами, владелец приложения создает лишь малую часть контента, а основная масса его поступает от пользователей.

SOA + B2C + Web 2.0 = высокая латентность

В мире Web 2.0 гибридные приложения, использующие технологию “mash-up”, зачастую используют сервисы и Web-каналы через сервисные интерфейсы SOA (см. заметку “Java EE и появление SOA”). Эти приложения работают с сервисами в соответствии с принципами B2C, например, гибридное приложение может смешивать данные, поступающие из различных источников – сведения о погоде, данные картографических сайтов и информацию от сервисов, отслеживающих трафик на дорогах. В этом случае время, затрачиваемое на обработку запросов, включает в себя затраты на получение всей необходимой информации. Тем не менее пользователи по-прежнему ожидают от приложений высокой производительности несмотря на рост числа источников данных и используемых внешних сервисов.

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

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

Повышенная интерактивность

Еще одна задача, которую Web 2.0 ставит перед разработчиками – это активное взаимодействие с пользователями, что приводит к повышенному числу серверных запросов со стороны каждого активного клиента. Это обусловлено следующими факторами:

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

Высокая латентность и клиентские каналы с малой пропускной способностью

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

Все эти факторы приводят к увеличению трафика и повышают число обращений к серверу по сравнению с приложениями Web 1.0. Этот трафик сложно контролировать в моменты пиковой нагрузки, несмотря на возможности Ajax, направленные на оптимизацию трафика (трафик Ajax-приложения зачастую меньше трафика обычного Web-приложения, обладающего идентичными функциями).

Больше контента

Приложения Web 2.0 обрабатывают больше информации, чем Web-приложения предыдущего поколения.

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

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

Постоянные соединения

Подключение к серверу со стороны клиента может занимать продолжительное время, поэтому, если ожидается несколько сеансов взаимодействия, имеет смысл повторно использовать ранее установленные соединения. Кроме того, постоянно установленные соединения удобно использовать для оповещения клиентов. Впрочем, клиенты приложений Web 2.0 зачастую находятся в сетях под защитой сетевых экранов, которые значительно затрудняют или даже запрещают прямые соединения с серверами. Допустим, приложение Ajax посылает запросы, проверяющие наступление того или иного события. Чтобы сократить количество запросов, некоторые Ajax-приложения используют паттерн Комета (Comet) (см. Ресурсы), в соответствии с которым, сервер держит соединение открытым до наступления события, а затем отсылает ответ клиенту.

Протоколы обмена сообщениями в пиринговых сетях, например SIP, BEEP и XMPP, все чаще начинают использовать постоянные соединения, впрочем, как и протоколы передачи потокового видео.

Повышенный риск слэшдот-эффекта

Из-за того, что приложения Web 2.0 могут иметь колоссальную аудиторию, некоторые сайты оказываются под угрозой так называемого слэшдот-эффекта (slashdot effect) – резкого увеличения трафика в результате упоминания сайта в популярном блоге, на новостной странице или в социальной сети (см. Ресурсы). Все сайты должны выдерживать трафик на несколько порядков интенсивнее, чем их нормальная нагрузка. В любом случае их производительность не должна резко падать в подобных случаях.


Латентность имеет значение

Латентность операций значительно сильнее сказывается на приложениях Java EE, чем их пропускная способность. Даже если используемые приложением сервисы могут производить огромное число операций, их латентность при этом остается неизменной или возрастает. Программные интерфейсы Java EE в своей массе плохо приспособлены к подобной ситуации, потому что она нарушает предположения о латентности, неявно заложенные в их дизайн.

Поддержка большой страницы форума или блога при использовании синхронного API требует отдельного потока выполнения. Если каждая страница требует на обработку одну секунду (что реально в случае приложений типа LiveJournal, которые работают с объемными страницами), а в пуле выделено 100 потоков, то сервер не сможет обрабатывать более сотни страниц в секунду, что совершенно недопустимо. При этом увеличение количества потоков в пуле помогает лишь до определенного предела, после которого начинает снижаться производительность работы сервера приложений.

Синхронные однопоточные API, заложенные в архитектуру Java EE, не позволяют использовать такие протоколы обмена сообщениями, как SIP, BEEP или XMPP. Ограниченность пула потоков при синхронной работе не дает серверу приложений возможности обрабатывать параллельные запросы во время передачи или получения сообщения по одному из вышеперечисленных протоколов. При этом необходимо учитывать, что сообщения не всегда бывают короткими (особенно в случае BEEP), и их генерирование может потребовать доступа к ресурсам других организаций, например, через Web-сервисы. При этом транспортные протоколы, такие как BEEP или SCTP (Stream Control Transmission Protocol), могут устанавливать несколько логических соединений поверх одного соединения TCP/IP, что еще больше затрудняет управление потоками.

Для реализации потоковых сценариев обработки Web-приложениям пришлось отказаться от стандартных приемов работы и интерфейсов Java EE. В частности, серверы на основе Java EE редко используются для приложений P2P или потокового видео. Гораздо активнее для поддержки необходимых протоколов применяются специальные компоненты, зачастую использующие коннекторы JCA (Java Connector Architecture) для реализации специальной асинхронной логики. Далее мы покажем, что контейнеры сервлетов нового поколения также поддерживают нестандартные интерфейсы для реализации паттерна Comet. Этот подход разительно отличается от стандартных сервлетных интерфейсов как по виду самих API, так и по способам их использования.

Наконец, как вы помните, одним из основополагающих принципов Java EE является то, что улучшение инфраструктуры сети может снизить продолжительность транзакций. В случае прямых видеотрансляций увеличение производительности сетевой инфраструктуры вообще не влияет на длительность обработки запроса, потому что видеопоток посылается клиенту по мере генерирования. Улучшение инфраструктуры может только позволить увеличить количество потоков для обслуживания большего количества клиентов, а также дать возможность вести трансляции в высоком разрешении.


Асинхронный принцип работы

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

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

Наглядная демонстрация преимуществ асинхронных API

Улучшение масштабируемости при использовании асинхронных API можно проиллюстрировать на примере простого сервлета. Если вы согласны, что асинхронные архитектуры – это достойный ответ на проблемы масштабируемости приложений Web 2.0, то можете смело переходить к разделу, описывающему возможные варианты применения Java EE в мире Web 2.0.

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

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

  • Соединения с базой данных. Этот ресурс обычно доступен Web-приложениям в виде объекта класса DataSource, содержащего ограниченное число соединений, которые могут использоваться параллельно.
  • Сетевые соединения. Этот ресурс используется для отправки ответа клиенту и для вызова Web-сервиса. До недавнего времени этот ресурс в большинстве серверов приложений был ограниченным. Однако серверы последнего поколения используют неблокирующий ввод-вывод (NIO), поэтому можно считать, что сервлету доступно столько сетевых соединений, сколько необходимо. Они используются в следующих ситуациях:
    1. Вызов Web-сервиса. Несмотря на то, что внешний сервис может принимать ограниченное число запросов, это количество как правило достаточно велико, поэтому продолжительность вызова определяется временем передачи данных по сети.

    2. Получение входящего запроса от клиента. В нашем примере используются запросы типа GET, поэтому данные затраты можно проигнорировать.

    3. Отправка ответа клиенту. Эти затраты также игнорируются, потому что в случае коротких ответов они могут буферизоваться в памяти сервера и отправляться по мере необходимости через NIO. Кроме того, если ответы короткие (а они будут именно такими в нашем примере), время их формирования также несущественно по сравнению со временем обработки запросов.

Допустим, что выполнение сервлета можно разделить на этапы, показанные в таблице 1.

Таблица 1. Время выполнения операций сервлетом (в условных единицах)
ЭтапДлительностьОперация
12 ед.Чтение параметров поступившего запроса
28 ед.Транзакция с локальной базой данных
32 ед.Обработка информации, полученной из базы данных, и подготовка вызова удаленного сервиса
416 ед.Вызов Web-сервиса с удаленного сервера
54 ед.Формирование ответа
Всего:32 ед.

На рисунке 1 показано распределение времени между бизнес-логикой, базой данных и Web-сервисом при работе сервлета:

Рисунок 1. Распределение времени между этапами работы сервлета
Distribution of time among steps

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

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

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

В случае низкой нагрузки синхронная и асинхронная модели будут показывать примерно одинаковую производительность. Если запрос к базе данных и вызов Web-сервиса могут выполняться параллельно, то асинхронный вариант будет быстрее. Но основной интерес представляют результаты работы в условиях перегрузки, например когда количество запросов достигает пикового значения. Допустим, одновременно пришло девять запросов. В синхронном случае контейнер сервлетов будет вынужден использовать три потока, а в асинхронном – только один.

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

Рисунки 2 и 3 были созданы с помощью простого симулятора, моделирующего работу с синхронным и асинхронным API соответственно:

Рисунок 2. Диаграмма при синхронных вызовах
Synchronous case

(Нажмите здесь для увеличения изображения)

Каждый прямоугольник на рисунке 2 представляет собой один этап выполнения процесса. Прямоугольники содержат пару чисел: номер процесса (от 1 до 9) и номер фазы внутри процесса. Каждому процессу соответствует свой цвет. Заметим, что запрос к базе данных и вызов Web-сервиса обозначены отдельными линиями, поскольку они выполняются независимо друг от друга: сервером базы данных и реализацией Web-сервиса соответственно. Контейнер сервлетов не выполняет никаких действий во время ожидания результатов. Подобное простаивание обозначено светло-серым цветом.

Ромбовидные маркеры внизу диаграммы обозначают моменты времени, соответствующие окончанию обработки запросов. Первое число маркера представляет собой время в условных единицах, а второе (необязательный параметр, заключенный в скобки) – количество процессов, завершившихся на данный момент времени. Из рисунка 2 видно, что первые два запроса завершились в момент времени 32, а последний – в момент времени 104.

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

Рисунок 3. Диаграмма при асинхронных вызовах
Asynchronous case

(Нажмите здесь для увеличения изображения)

На рисунке 3 можно отметить несколько интересных моментов. Обработка первого запроса завершается на 23% позже, чем в синхронном случае. Зато последний запрос завершается на 26% раньше, и это при том что используется в три раза меньше потоков. Время, выделяемое на обработку запросов, распределяется значительно равномернее, благодаря чему пользователи регулярнее получают результаты. Например, если разница во времени обработки первого и последнего запроса в синхронном случае была 225%, то в асинхронном – всего 80%.

Далее предположим, что мы модернизировали серверы приложений и базы данных таким образом, что они стали работать вдвое быстрее. Хронометраж работы приведен в таблице 2 (единицы аналогичны используемым в таблице 1):

Таблица 2. Хронометраж выполнения операций сервлетом после модернизации
ЭтапДлительностьОперация
11 ед.Разбор поступившего запроса
24 ед.Транзакция с локальной базой данных
31 ед.Обработка информации, полученной из базы данных, и подготовка вызова удаленного сервиса
416 ед.Вызов Web-сервиса с удаленного сервера
52 ед.Формирование ответа
Всего:24 ед.

Как видите, общее время обработки запроса составило 24 единицы или 3/4 от изначального времени.

На рисунке 4 показано новое распределение времени между бизнес-логикой, базой данных и Web-сервисом:

Рисунок 4. Распределение времени между этапами работы после модернизации
Distribution of time between steps after upgrade

Результаты синхронного выполнения показаны на рисунке 5. Общее время работы снизилось примерно на 25%, но при этом картина распределения времени осталась прежней, а потоки стали проводить еще больше времени в состоянии ожидания.

Рисунок 5. Диаграмма при синхронных вызовах после модернизации
Synchronous case after upgrade

(Нажмите здесь для увеличения изображения)

На рисунке 6 показаны результаты работы с использованием асинхронных интерфейсов:

Рисунок 6. Диаграмма при асинхронных вызовах после модернизации
Asynchronous case after upgrade

(Нажмите здесь для увеличения изображения)

Результаты асинхронной работы очень интересны. Процесс обработки запросов значительно лучше масштабируется при увеличении производительности серверов приложений и базы данных. При этом распределение времени обработки между запросами стало еще более равномерным; разница между самым быстрым и самим медленным запросами сократилась до 57%. Общее время работы (до момента завершения последнего запроса) составило всего 57% от изначального, что значительно лучше 75% в случае синхронной работы. Последний запрос (номер 9 в обоих случаях) обрабатывается более чем на 40% быстрее, чем в синхронном случае, при том что отставание первого запроса сократилось на 14%. Вдобавок при использовании асинхронных интерфейсов можно выполнять большее количество параллельных вызовов Web-сервисов. В синхронном случае степень параллелизма была ограничена количеством потоков в пуле сервлета. Таким образом, даже если Web-сервис был способен обслуживать больше запросов, они не могли быть отправлены, потому что сервлет находился в режиме ожидания.

Результаты практических тестов подтверждают, что асинхронные приложения лучше масштабируются и стабильнее работают при пиковых нагрузках. Латентность является очень сложной проблемой, и закон Мура (см. Ресурсы) не обещает здесь значительных улучшений. Несмотря на то, что ширина каналов связи постоянно растет, латентность не уменьшается и даже иногда возрастает. Поэтому разработчикам не остается ничего другого, кроме как реализовывать поддержку асинхронных интерфейсов со стороны серверов приложений.

Существует множество вариантов реализации асинхронных систем, но ни один из них пока не утвердился в качестве фактического стандарта. Каждый подход имеет свои преимущества и недостатки, которые могут по-разному проявляться в различных ситуациях. Далее в статье будет рассказано о механизмах создания асинхронных Java-приложений, ориентированных на обработку событий. Не останутся без внимания плюсы и минусы каждого из подходов.


Общие подходы

Ad-hoc параллелизм и NIO

Начиная с версии 1.4, Java содержит реализацию неблокирующего сетевого API ввода-вывода – NIO (классы java.nio.*). Кроме того, в Java 1.5 улучшены средства для параллельной работы (java.util.concurrent.*). Неблокирующий ввод-вывод и параллелизм позволяют создавать приложения с поддержкой большого числа параллельных соединений, используя доступные API и технологии.

К сожалению, эти интерфейсы являются слишком низкоуровневыми и неудобными для использования за исключением случаев, когда повысить производительность по-другому нельзя. «Низкоуровневость» особенно бросается в глаза при работе с NIO, который крайне трудно использовать для чего-либо сложнее, чем копирование потоков данных. Еще одной проблемой является создание независимых модулей, работающих с общим селектором NIO. Для решения подобных проблем нужна библиотека, предоставляющая оболочки для классов NIO.

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

Приложения, созданные с помощью средств организации параллелизма, менее подвержены проблемам, связанным с многопоточностью, потому что Java 5 поддерживает достаточно высокоуровневые операции. К сожалению, по-прежнему существует серьезная опасность возникновения взаимных блокировок, причины которых очень сложно обнаружить в процессе отладки.

Были предприняты попытки спроектировать общую схему асинхронного взаимодействия в рамках платформы Java. Все предлагаемые подходы были основаны на обмене сообщениями, в частности, нередко используются вариации акторной модели (actor model) для определения объектов. В остальных аспектах, таких как простота использования, необходимые библиотеки и т.д., решения сильно различаются. В разделе Ресурсы приведены ссылки на Web-сайты, описывающие сами проекты и сопутствующую информацию.

Ступенчатая событийная архитектура

Ступенчатая событийная архитектура (Staged event-driven architecture - SEDA) – это интересное решение, сочетающее в себе идеи асинхронного программирования и автономных вычислений. SEDA была одним из главных полигонов для испытаний API Java NIO, появившегося в J2SE 1.4. Несмотря на то, что работа над самим проектом прекратилась, SEDA стала своего рода планкой масштабируемости и адаптивности Java-приложений, а заложенные в ней идеи, относящиеся к асинхронному программированию, оказали влияние на другие проекты.

В SEDA совмещаются синхронные и асинхронные API, что привело к интересным результатам. Архитектура оказалась значительно более пригодной к применению, чем ad-hoc параллелизм, но все же не завоевала широкой популярности среди пользователей.

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

  • Увеличение или уменьшение числа потоков в зависимости от нагрузки, что обеспечивает динамическую адаптацию компонентов к интенсивности использования. Если какой-то из компонентов испытывает всплеск обращений, он выделяет себе потоки. При бездействии компонента потоки освобождаются.
  • Изменение поведения в зависимости от нагрузки. Например, в случае повышенной нагрузки можно генерировать упрощенные версии страниц – например, без изображений, с урезанной функциональностью и скриптами. При этом пользователи могут использовать приложение, но оно генерирует меньше запросов и расходует меньше трафика.
  • Отказ приема запросов на обработку и блокирование ступеней, от которых поступают запросы.

Первые два пункта особенно полезны, они являются разумным воплощением идей автономных вычислений. Третий, однако, является одной из причин, почему эта архитектура не получила широкого распространения. Из-за этого пункта возникает риск взаимной блокировки компонентов, поэтому требуются специальные усилия на этапе проектирования приложения, чтобы его избежать. Существуют и другие причины, осложняющие использование SEDA:

  • Ступени зачастую являются слишком крупными компонентами в архитектуре приложения. Например, компонентом может являться сетевой интерфейс с поддержкой HTTP. Рассматривая его как единое целое, сложно решить такую проблему как ограниченная ширина каналов передачи данных для некоторых клиентов.
  • Трудность возвращения результатов асинхронных вызовов. Результаты просто передаются ступеням в надежде, что ступень самостоятельно свяжет его с выполненной ранее операцией.
  • Синхронность большинства библиотек на Java. SEDA не стремится последовательно изолировать синхронные участки кода от асинхронных, что повышает опасность случайного блокирования ступени в результате ошибки.

Наиболее часто используемым проектом, в котором реализованы идеи SEDA, является Apache MINA (см. Ресурсы). Он применяется в потоковом сервере OSFlash.org Red5, проекте Apache Directory Project, а также XMPP-сервере Jive Software Openfire.

Язык программирования E

Выражаясь формально, Е – это динамически типизированный, функциональный язык программирования, а не инфраструктура разработки приложений. Он предоставляет средства для безопасных распределенных вычислений, а также интересные конструкции для асинхронного программирования. Несмотря на то, что его официальными предками называют Joule и Concurrent Prolog, его синтаксис и поддержка параллелизма выглядят более привычно для разработчиков, имеющих опыт работы с такими популярными императивными языками как Java, JavaScript и C#.

Текущая версия E реализована на основе Java и Common Lisp и может использоваться из приложений на Java. Однако существует несколько препятствий для использования E в серверных приложениях, работающих под высокой нагрузкой. Большинство проблем обусловлено молодостью языка и, вероятно, будет вскоре исправлено. Сложности также возникают из-за динамической природы E, но они в основном не касаются предоставляемой им средства поддержки параллелизма.

Е включает в себя следующие основные конструкции для поддержки асинхронного программирования:

  • Контейнеры объектов (vat’ы). Все объекты находятся в контексте какого-либо vat’a, запрещающего синхронный доступ из других vat’ов.
  • Promise’ы – переменные для представления результатов асинхронных операций. Первоначально они находятся в неопределенном состоянии, что говорит о незавершенности операции. Затем переменной присваивается некий результат (операция resolve), либо выставляется флаг ошибки (операция smash).
  • Объекты могут получать сообщения и локальные вызовы. Локальные объекты могут вызываться синхронно, с помощью операции немедленного вызова (immediate call), или асинхронно, с помощью операции окончательной пересылки (eventual send). К удаленным объектам доступ разрешается только c помощью асинхронной пересылки, которая приводит к созданию promise'а. Для синхронных и асинхронных вызовов служат операторы. и <- соответственно.
  • Явное создание promise'ов. В этом случае необходима ссылка на асинхронно вызванный объект, которая может быть передана в другие контейнеры. Через эту ссылку доступны два метода – resolve и smash.
  • Оператор when, позволяющий выполнить необходимые действия в случае, если promise’у было присвоено значение или выставлен флаг ошибки. Код, вызываемый оператором when, рассматривается как замыкание, и из него возможен доступ к объектам, размещенным во внешней области видимости. Это решение напоминает анонимные внутренние классы в Java, у которых есть доступ к объявлениям, расположенным в области видимости метода главного класса.

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

Е поднимает планку применимости асинхронного программирования на практике. Поддержка параллелизма слабо связана с другими возможностями Е и может быть добавлена в существующие языки. Средства, предоставляемые Е, в настоящее время обсуждаются в контексте развития таких языков, как Squeak, Python и Erlang. Он вполне может оказаться более полезным инструментом, чем более узко специализированные возможности других языков, например, итераторы в C#.

Библиотека AsyncObjects

Целью проекта AsyncObjects является создание на чистом Java инфраструктуры, удобной для разработки асинхронных компонентов. Он сочетает в себе архитектуру SEDA и язык программирования E. Из Е он заимствует базовые механизмы для поддержки параллелизма, а из SEDA – инструменты для интеграции с синхронными API Java. Первый прототип AsyncObjects был выпущен в 2002 г., после чего работа над проектом практически остановилась до недавнего времени. Е убедительно показал, насколько практичным может быть асинхронное программирование, а AsyncObjects преследует ту же цель, но оставаясь в рамках чистого Java.

Аналогично SEDA, приложение состоит из нескольких циклов обработки событий, но пока в проекте не реализована ни одна из возможностей саморегулирования, предоставляемых SEDA. Вместо этого используется упрощенный механизм для балансировки нагрузки ввода-вывода, поскольку компоненты AsyncObjects значительно мельче, а для получения результатов асинхронных операций применяются promise'ы.

В AsyncObjects используются те же понятия для описания работы асинхронных компонентов, что и в E, а именно: vat'ы и promise'ы. Поскольку вводить новые операторы в чистом Java нельзя, не каждый объект может выступать в роли асинхронного компонента. Объект должен быть наследником определенного базового класса, реализующего асинхронный интерфейс. Реализация этого интерфейса, предоставляемая AsyncObjects, посылает сообщения vat'у, в котором находится компонент, а тот, в свою очередь, передает их самому компоненту.

Текущая версия (0.3.2) совместима с Java 5 и поддерживает шаблоны (generics). Если Java NIO реализован под данной платформой, то AsyncObjects будет использовать его, если же нет – возможна работа через обычные сокеты.

Основной проблемой AsyncObjects является слабо развитая библиотека классов, что объясняется трудностями интеграции с синхронными интерфейсами Java. На текущий момент реализована только библиотека сетевого ввода-вывода. При этом есть надежда, что появление таких средств как поддержка асинхронных Web-сервисов в Axis2 и сервлеты Comet в Tomcat 6 (см. раздел “API, специфичные для сервлетов и операций ввода-вывода”), частично решит эту проблему.

API-интерфейс ref_send

Интерфейс ref_send, поддерживаемый платформой Waterken – это еще одна попытка реализовать идеи E на Java. Большая часть ref_send написана на подмножестве Java, получившем название Joe-E.

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

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

Frugal Mobile Objects

Frugal Mobile Objects (экономичные мобильные объекты) – это реализация акторной модели, специально спроектированная для работы в условиях ограниченности ресурсов, например, в среде Java ME CLDC 1.1. В ней применяются интересные архитектурные принципы, направленные на экономное использование ресурсов и при этом не приводящие к серьезному усложнению интерфейсов.

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

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

Акторы в Scala

Scala – это очередной язык программирования для платформы Java. Он представляет собой надмножество Java, но при этом имеет несколько другой синтаксис. В ряде случаев Scala оказывается удобнее в использовании, чем Java.

Одной из интересных возможностей Scala является поддержка параллелизма, реализованная на основе акторов, аналогичных применяемым в языке программирования Erlang. Над архитектурой данного решения по-прежнему продолжается работа, но сама функциональность уже вполне пригодна к использованию и полностью поддерживается синтаксисом языка. При этом поддержка параллелизма в стиле Erlang, реализованная в Scala, все же уступает аналогичным функциям E в смысле удобства использования и автоматизированности.

Модель Scala также имеет определенные проблемы с безопасностью, потому что ссылка на вызывающий объект передается в теле каждого сообщения, что позволяет вызываемому компоненту в свою очередь делать вызовы методов, вместо того чтобы просто вернуть требуемое значение. В этом смысле модель E, основанная на promise'ах, обеспечивает более надежный контроль. Кроме того, в Scala еще не до конца реализован механизм взаимодействия с блокирующими участками кода.

Основным преимуществом Scala является компиляция в байт-код JVM, поэтому в теории он может использоваться в приложениях Java SE и Java EE напрямую и без потери производительности. Однако его пригодность для широкого коммерческого использования еще предстоит установить, так как, в отличие от Java, у Scala пока нет достаточной поддержки со стороны IDE и, в отличие от Java, он не опирается на производителей программного обеспечения. Таким образом, на текущий момент Scala рискованно применять в длительных проектах, но он вполне может быть интересным вариантом в случае проектов с коротким жизненным циклом, например, прототипов.


API, специфичные для сервлетов и операций ввода-вывода

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

Тем не менее эти попытки заслуживают внимания, так как они являются показателем необходимости реализации асинхронных компонентов. В разделе Ресурсы приведены ссылки на Web-сайты, содержащие описания этих проектов и сопутствующую информацию.

JSR 203 (NIO.2)

JSR 203 – это доработанный вариант API NIO. На момент написания этой статьи он все еще находился в черновом варианте и мог существенно измениться в процессе работы. Этот API планируется включить в Java 7.

В JSR 203 предлагается концепция асинхронных каналов. Она направлена на облегчение многих трудностей, испытываемых программистами, но при этом похоже, что сам интерфейс будет достаточно низкоуровневым. Вдобавок JSR 203 содержит долгожданный асинхронный интерфейс файлового ввода-вывода, которого не было в предыдущих версиях, а также типы IoFuture и CompletionHandler, облегчающие использование классов из других библиотек. В целом новый асинхронный API NIO должен быть удобнее API предыдущего поколения, основанного на селекторах. Вполне вероятно, что для простых задач его можно будет использовать напрямую, без необходимости написания классов-оболочек.

Однако существует и серьезный недостаток: этот интерфейс узко специализирован для работы с файловым и сокетным вводом-выводом и не предоставляет более высокоуровневых средств для создания асинхронных компонентов. Таким образом, при создании высокоуровневых классов придется использовать специальные подходы для решения проблем, которые будут повторяться от компонента к компоненту. Возможно, это окажется удачным техническим решением, учитывая, что до сих пор не существует стандартного подхода к разработке асинхронных компонентов на Java.

Glassfish Grizzly NIO

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

Continuations в Jetty 6

Jetty предлагает весьма нетрадиционный подход, основанный на понятии continuation (преемственность). Как правило, использование исключений для реализации логики работы API является очень спорным решением (хотя существуют и другие мнения, см. блог Грега Уилкинса, ссылка приведена в разделе Ресурсы). Сервлет может запросить объект continuation и вызвать у него метод suspend(), задав определенный тайм-аут. Этот метод может выдать исключение. После этого можно вызвать метод resume(), или же continuation возобновит работу после истечения тайм-аута.

Таким образом, continuations в Jetty 6 представляют собой попытку реализации синхронного API, обладающего асинхронной семантикой. При этом подобное поведение может оказаться неожиданным для клиентов, потому что сервлет возобновит обработку запроса с начала метода, а не с точки вызова метода suspend().

API Comet в Apache Tomcat 6

API-интерфейс Comet в Tomcat был разработан специально для поддержки паттерна взаимодействия Comet. Контейнер сервлетов посылает уведомления сервлетам о переходах из одного состояния в другое и о том, доступны ли данные для чтения. Это более разумный и простой подход по сравнению с Jetty. В нем используются обычные синхронные API для потокового чтения и записи данных. При аккуратном использовании реализованный таким образом API не должен блокировать потоки.

JAX WS 2.0 и клиентский API для асинхронного вызова Web-сервисов в Apache Axis2 (Asynchronous Web Service Client API)

JAX WS 2.0 и Axis2 предоставляют API для неблокирующего вызова Web-сервиса. Удаленный сервер самостоятельно уведомляет переданного ему слушателя об окончании вызова. Это открывает новые возможности для использования Web-сервисов, даже со стороны Web-клиентов. Несколько независимых вызовов одного Web-сервиса, сделанных одним сервлетом, теперь могут быть обслужены параллельно, что минимизирует задержку на стороне клиента.


Заключение

Необходимость в асинхронных компонентах в Java в настоящее время признается все шире, и область разработки асинхронных приложений развивается бурными темпами. Наиболее крупные контейнеры сервлетов с открытым кодом (Tomcat и Jetty) предоставляют некоторую поддержку, по крайней мере, для сервлетов, при создании которых разработчики испытывают наибольшие проблемы. Некоторые библиотеки на Java предлагают асинхронные интерфейсы, но этим попыткам не хватает координированности, а сами интерфейсы оказываются плохо совместимыми между собой в связи с проблемами по управлению потоками и т.д. Поэтому необходимы контейнеры, способные содержать множество различных асинхронных компонентов от разных поставщиков.

На данный момент пользователям приходится выбирать из множества вариантов, каждый из которых имеет свои преимущества и недостатки в разных ситуациях. Примером библиотеки, предоставляющей готовую поддержку асинхронных вызовов для определенных сетевых протоколов, является Apache MINA – она может быть полезна в случае, если планируется работа с одним из этих протоколов. В Apache Tomcat 6 реализована хорошая поддержка паттерна взаимодействия Comet, благодаря чему он удобен, если асинхронное взаимодействие будет происходить в соответствии с этим паттерном. Если же приходится разрабатывать приложения с нуля и очевидно, что ни одна из готовых библиотек не подходит, то можно выбрать AsyncObjects, содержащий большой набор удобных интерфейсов. Он так же может быть полезен для создания оболочек вокруг существующих библиотек асинхронных компонентов.

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

Центр материалов по Ajax на сайте developerWorks
Обратитесь к центру материалов по Ajax – единому собранию бесплатных утилит, кода и информации о разработке Ajax-приложений. С помощью активного форума сообщества Ajax, модерируемого экспертом Джеком Херрингтоном (Jack Herrington), вы сможете общаться с коллегами, возможно, знающими решение проблемы, над которой вы ломаете голову в данный момент.

Ресурсы

  • Примите участие в обсуждении материала на форуме.
  • Оригинал статьи: “Java EE meets Web 2.0” (Константин Плотников, Артем Папков и Джим Смит, developerWorks, ноябрь 2007 г.). (EN)
  • Прочитайте о ECPerf 1.1, SPECjbb2005 и SPECjAppServer2004 - стандартных тестах Java EE для измерения производительности. (EN)
  • Посетите блогу Грега Уилкинса (Greg Wilkins). (EN)
  • Ознакомьтесь со статьей "Ease the integration of Ajax and Java EE" (Патрик Гэн (Patrick Gan), developerWorks, июль 2006 г.), в которой рассматривается влияние, которое могут оказать технологии Ajax на весь процесс разработки, если начать их использовать в Web-приложениях Java EE.
  • Обратитесь к документу JSR 109: Implementing Enterprise Web Services, в котором описываются модель и среда выполнения для разработки Web-сервисов на Java. (EN)
  • Прочитайте статью "Why Ajax Comet?" (Грег Уилкинс, webtide, июль 2006 г.), описывающую паттерн Comet. (EN)
  • Хорошее описание слэшдот-эффекта приведено в статье Стивена Адлера (Stephen Adler) "The Slashdot Effect: An Analysis of Three Internet Publications". (EN)
  • Подробное описание SEDA, а также преимуществ асинхронной архитектуры приложений, можно найти в статье "SEDA: An Architecture for WellConditioned, Scalable Internet Services" (Мэтт Уэлш (Matt Welsh), Дэвид Каллер (David Culler) и Эрик Брюер (Eric Brewer), Университет Калифорнии в Беркли). (EN)
  • Обратитесь к статье в Wikipedia, объясняющей Закон Мура. (EN)
  • Зайдите на страницу проекта Apache MINA. (EN)
  • Зайдите на сайт SEDA. (EN)
  • Посетите ERights.org – официальный сайт языка программирования E. С него можно скачать книгу The E Language in a Walnut, рассказывающую об основах языка. (EN)
  • Зайдите на домашнюю страницу проекта AsyncObjects Framework Home Page. (EN)
  • Узнайте больше об интерфейсе ref_send на сайте Waterken Server. (EN)
  • Прочитайте статью Бенуа Гарбинато (Benoit Garbinato) "Frugal Mobile Objects", описывающую данную инфраструктуру. (EN)
  • Посетите официальный сайт языка программирования Scala. (EN)
  • Обратитесь к статье Actors that Unify Threads and Events" (Филипп Халлер (Philipp Haller) и Мартин Одерски (Martin Odersky), январь 2007 г.), в которой рассматривается поддержка параллелизма в последних версиях Scala. (EN)
  • Ознакомьтесь с документом JSR 203: More New I/O APIs for the Java Platform ("NIO.2"), в котором описываются API для доступа к файловой системе, масштабируемые асинхронные операции ввода-вывода, механизм привязки socket-channel и его конфигурирование, а также широковещательные датаграммы. (EN)
  • Прочитайте статьи "Grizzly NIO Architecture: part II" (Жан Франсуа Аркан (Jean-Francois Arcand), java.net, январь 2006 г.) и "Grizzly part III: Asynchronous Request Processing (ARP)" (Жан Франсуа Аркан, java.net, февраль 2006 г.), описывающие архитектуру Grizzly. (EN)
  • Ознакомьтесь с понятием continuation в Jetty. (EN)
  • Обратитесь к разделу Advanced IO and Tomcat в документации по Apache Tomcat 6.0, в котором приводится информация о HTTP-коннекторе NIO для сервера Tomcat. (EN)
  • Прочитайте руководство пользователя Apache Axis2 Advance User's Guide, содержащее обзор возможностей асинхронного вызова Web-сервисов, предлагаемых Axis2. (EN)
  • В статье "Asynchronous Web Service Invocation with JAX-WS 2.0." (Янг Йенг (Young Yange), java.net, сентябрь 2006 г.) рассматривается поддержка асинхронного вызова Web-сервисов в JAX-WS 2.0. (EN)
  • Обратитесь к центру Ajax на сайте developerWorks, содержащему большое количество утилит, примеров кода и прочей информации, которые помогут вам начать создавать приложения Ajax уже сегодня.
  • Web 2.0 на сегодняшний день является популярной темой в кругах разработчиков Web-приложений. Большое количество материалов по Web 2.0 можно найти в разделе Web-разработки.

Комментарии

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-архитектура, Технология Java, XML
ArticleID=332924
ArticleTitle=Java EE в мире Web 2.0
publish-date=08252008