Jetty Continuations. Тестовое приложение

от автора

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

Задание было примерно следующего содержания:

Разработать HTTP сервер пердоставляющий информацию об изменениях котировок на фондовом рынке. Основным требованием является минимальная задержка доставки информации об обновлении котировок. Это означает что инетрвал времени между изменение коториовки и отображением измения на веб-страницы должен быть минимальным на сколько это возможно. Сервер должен принимать AJAX запросы на обновление котировок из браузера(например об обновление котировок ИБМ, или Микрософт) и посылать обновляющие сигналы тогда когда цена измениться. Важно помнить что котировки обновляются не синхронно, а со случайной периодичностью и не стоит надеяться на их синхронное обновление. Приложение должно быть способно поддерживать большое число long-polling подключений (~100) используя при этом не более чем 20 потоков. Это означает что клиентские подключения замораживаются пока запрошенные котировки не изменятся, но не более чем на минуту. Другими словами сервер должен реализовывать Comet (Revers-Ajax, Server push).

Надо сказать с заданием я справился, посему решил поделится своими наработками. Я не знаю насколько эта информация актуальна сейчас, но все же для образовательных целей подойдет. Важно, я использую Jetty 6 Continuations (http://docs.codehaus.org/display/JETTY/Continuations), в Jetty 7 вроде как появиться альтернативные механизмы.

В чем суть проблеммы

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

А как мы знаем стандартная модель обработки подключений предполагает выделение одного потока на одно подключение, таким образом если у вас 100 подключений — значит у вас 100 потоков, но врядли Ваш сайт рассчитан на 100 пользователй так ведь 🙂 Здесь приведена любопытная табличка, показывающая сколько Вам потоков потребуется что бы Ваши клиенты остались довольны, в зависимости от используемых технологий это число очень разнится. И естественно, побеждает, кто бы вы думали?

Jetty Continuations

Jetty Continuations — это такое новое АПИ предоставляемое веб-серверами Jetty (начиная с 6 версии). Оно позволяет использовать так называемый «Continuations» объект для сохранения обрабатываемого запроса (если ответ допустим еще не готов, как в нашем случае — котировки не изменились) и освобождение потока.

На языке кода, это выглядит примерно так:

<font size="2" face="Courier New" color="black">    RetryContinuation continuation = (RetryContinuation)         ContinuationSupport.getContinuation(request, continuations);     continuation.suspend(60 * 1000);</font> <font size="1" color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font size="1" color="gray">Source Code Highlighter</font></a>.</font>

Первой строчкой мы формируем «Continuations» объект, а второй строчкой говорим приостановить обработку запроса до появления новых данных, но не более чем на 60 секунд, автоматически после вызова этой команды поток будет освобожден и может быть снова использован для обработки других запросов.

Когда же данные у нас обновяться мы можем просто вызвать у сохранненого «Continuations» объекта resume(), что бы вновь инициировать обработку запроса.

Как это работает

Когда мы вызываем метод suspend(timeout), то бросается RetryRequest (runtime exception), это исключение не обрабатывается специальным образом самим Jetty — Jetty помещает запрос в timeout-очередь и возвращает поток в пул потоков. Когда вызывается resume(), или timeout истекает запрос повторяется.

Выполненное тестовое задание с очень подробным readme можно скачать тут, кому интересно — с легостью разбируться, у меня очень юзер френдли 🙂

ссылка на оригинал статьи http://habrahabr.ru/post/106454/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *