Javascript.RU

Передача данных по инициативе сервера, обзор COMET

Update: Более новый материал по этой теме находится по адресу https://learn.javascript.ru/xhr-longpoll.

COMET-технологии позволяют организовать обновление данных на странице без участия пользователя.

Чаты, интернет-почта и многопользовательские админки - далеко не полный список, где они применимы.

В этом цикле статей - подробно описаны многочисленные тонкие моменты и решения частых проблем.

COMET (или "server push") - способ передачи данных с сервера на клиент, по инициативе сервера.

Например, у вас есть электронный магазин, и менеджер может отслеживать переходы клиента.
COMET позволяет менеджеру тут же, онлайн, спросить клиента о чем-то, предложить интересный вариант.

"По инициативе сервера" означает, что клиент сам не запрашивает сервер, он просто находится на странице.

Старейший пример COMET - чат. Человек просто находится на странице и получает новые сообщения.

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

Способов реализации COMET достаточно много. У них - самые разные характеристики, достоинства и недостатки.
Есть два основных класса.

Каждое событие на сервере браузер получает отдельным запросом. Здесь есть два основных метода.

  1. Частый опрос (polling)
  2. Длинный опрос (long-poll)

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

<events> 
  <message> 
    <from>Vasya</from> 
    <text>Привет!</text> 
  </message> 
  <notification> 
    <type>processing</type> 
    <text>Обработка завершена</text> 
  </notification> 
</events>

При очередном подключении браузер получает сразу весь пакет событий к настоящему моменту.

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

Канал связи разрывается время от времени:

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

Кроме того, для измерения сетевых задержек и контроля соединения, сервер может периодически посылать по этому каналу ping-пакеты.

  1. Бесконечный IFrame
  2. XMLHTTPRequest, interactive
  3. Multipart XMLHTTPRequest
  4. Event-source

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

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

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

Решение - добавлять к каждому сообщению 2K пробелов.

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

IFrame, который служит для передачи сообщений, НЕ должен сжиматься gzip/deflate. Иначе говоря, для служебного URL сообщений сжатие должно быть отключено.

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

Это - неприятное последствие хакерской натуры iframe. Например, в long poll сжатие проходит на ура, т.к события не являются частью одной страницы.

Не забудьте отключить буферизацию сервером. В связке Apache/PHP - отключите output buffering и включите ob_implicit_flush:

while (@ob_end_flush()) {}
ob_implicit_flush(1);

// ну и конечно убрать лимит на время выполнения скрипта
set_time_limit(0);

Как всегда, при написании веб-приложения встает вопрос о выборе архитектуры. С одной стороны, решения на длинных соединениях (все, кроме частых опросов) обеспечивают быстрое уведомление. С другой... Всегда ли длинное соединение лучше частых опросов?
Решение с длинными соединениями с виду оптимальнее, но гораздо сложнее и обладает рядом особенностей.

  1. Реализация длинного коннекта, как правило, усложняет архитектуру. Возможно, можно обойтись решением попроще?
  2. Ряд веб-серверов плохо оптимизированы под большое количество длинных соединений. Например, используются потоки или процессы, которые отъедают фиксированное количество ресурсов и не освобождают их до конца соединения.На уровне OS проблема решается использованием kqueue(FreeBSD) или epoll(Linux).На уровне веб-сервера можно использовать
    1. Apache MPM event для apache 2.2 (экспериментальный и ограниченный MPM, специальный поток обрабатывает Listening и Keep-Alive сокеты)
      не работает как следует с mod_perl/mod_php
    2. Jetty (Java) / Twisted(Python), nginx и другие специализированные серверы c одним потоком/процессом на много клиентов.

    Потянет ли текущая серверная архитектура длинные соединения? Ответ неочевиден для сотен/тысяч одновременных соединений, но, скажем, до 100 соединений в любой архитектуре все хорошо.

  3. Насколько долго пользователи находятся на одной и той же странице? При переходах коннект, скорее всего, придется открывать заново в любом случае.
  4. Если допустимы задержки доставки событий, то, может быть, хватит частого опроса?

Посмотрим на взаимодействие клиент-сервер "с высоты птичьего полета", выше деталей передачи данных, транспортов и т.п. Например, так это сделано в специализированном server-push движке lightstreamer.

Соединения с сервером делятся на два типа

  1. Control connection - контрольные соединения, через которые клиент отправляет запросы на сервер. Это - обычные AJAX-запросы через XMLHTTPRequest.
  2. Push connection(channel) - поток событий, соединение, через которые клиент получает события с сервера

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

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

  1. Клиент открывает потоковое соединение к серверу
  2. Клиент подписывается на события типа Item1 в схеме Schema1
  3. Сервер шлет события
  4. Клиент отписывается от событий через новое контрольное соединение
  5. Клиент закрывает соединение

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

В качестве транспорта в lightstreamer используется iframe. Время от времени его необходимо закрывать для очистки от принятых объектов. При закрытии сессии (это же происходит при refresh страницы в браузере) сервер буферизует новые события до некоторого таймаута и отдает их, как только открывается новая сессия Stream Connection 2 того же пользователя.

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


Автор: OS master (не зарегистрирован), дата: 4 сентября, 2008 - 01:52
#permalink

Скажите, а как при помощи mpm event решить вопрос создания апачем файлов от юзеров, которым принадлежит папка, в которой работает скрипт, а не nobody.
Спасибо!


Автор: Илья Кантор, дата: 4 сентября, 2008 - 08:15
#permalink

Вообще-то это не по теме, но все равно ответ - никак


Автор: Гость (не зарегистрирован), дата: 9 февраля, 2023 - 10:25
#permalink

Learning how to communicate with other snake game means learning more about yourself and your own emotional development.


Автор: Анатолий (не зарегистрирован), дата: 2 декабря, 2008 - 21:34
#permalink

неужели в этом можно разобраться?


Автор: Илья Кантор, дата: 3 декабря, 2008 - 11:30
#permalink

Изображения вверху записаны в UML-нотации. Конкретнее - это диграммы последовательности (sequence diagram).

Возможно, проще (и полезнее) - разобраться сначала с sequence diagram в UML вообще, а потом - в конкретными диаграммами здесь.


Автор: Гость (не зарегистрирован), дата: 6 января, 2010 - 16:07
#permalink

А сорс есть?


Автор: dima0000 (не зарегистрирован), дата: 16 марта, 2010 - 09:48
#permalink

я хотел бы написать на perl такой чат c jquery

можете ли вы подсказать как в этом разобратся?
нужно написать демона на сокетах? как это все будет?


Автор: Valery (не зарегистрирован), дата: 31 августа, 2010 - 16:45
#permalink

Илья,

Есть ли у Вас информация о том какие из методов используют большие компании вроде Facebook (чат, оповещения), Gmail (чат), Twitter (notifications)?


Автор: Илья Кантор, дата: 31 августа, 2010 - 20:32
#permalink

Добрый день!

Facebook - Tornado (их разработка, Open Source, Python), Gmail - свой сервер, клиентская часть - open source Google Closure Library, Twitter - не в курсе...

--
Илья


Автор: Гость (не зарегистрирован), дата: 14 октября, 2010 - 21:43
#permalink

Twitter - Erlang и Scala


Автор: Илья Кантор, дата: 15 октября, 2010 - 10:10
#permalink

Источник?


Автор: dordle12 (не зарегистрирован), дата: 16 августа, 2023 - 12:50
#permalink

I value your message, and I'm looking forward to hearing what you say. Play with me if you have time at a terrific game I found called dordle.


Автор: TOTOBLOG (не зарегистрирован), дата: 16 октября, 2023 - 06:24
#permalink

I think that's one of the very important information for me. And I'm glad to study your article. But I'd like to comment on some general things. The website tastes good, and the articles are actually great: D. Good process, cheers. 검증된메이저사이트


Автор: Аннакенна (не зарегистрирован), дата: 16 ноября, 2023 - 07:05
#permalink

В этом тексте описывается rice purity test COMET, метод передачи данных с сервера клиенту при запуске с сервера. COMET используется во многих приложениях, таких как чат, электронная почта и многопользовательское управление. Существует два основных метода развертывания COMET: опрос (регулярное исследование) и длительный опрос (долгосрочное исследование).


Отправить комментарий

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.
Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешены HTML-таги: <strike> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <u> <i> <b> <pre> <img> <abbr> <blockquote> <h1> <h2> <h3> <h4> <h5> <p> <div> <span> <sub> <sup>
  • Строки и параграфы переносятся автоматически.
  • Текстовые смайлы будут заменены на графические.

Подробнее о форматировании

CAPTCHA
Антиспам
4 + 1 =
Введите результат. Например, для 1+3, введите 4.
 
Текущий раздел
Поиск по сайту
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Последние комментарии
Последние темы на форуме
Forum