Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
84 lines (51 sloc) 5.17 KB

COMET с XMLHttpRequest: длинные опросы

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

Частые опросы

Первое решение, которое приходит в голову для непрерывного получения событий с сервера -- это "частые опросы" (polling), т.е периодические запросы на сервер: "эй, я тут, изменилось ли что-нибудь?". Например, раз в 10 секунд.

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

При этом, однако, возможна задержка между появлением и получением данных, как раз в размере этих 10 секунд между запросами.

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

- Задержки между событием и уведомлением.
- Лишний трафик и запросы на сервер.
+ Простота реализации.

Причём, простота реализации тут достаточно условная. Клиентская часть -- довольно проста, а вот сервер получает сразу большой поток запросов.

Даже если клиент ушёл пить чай -- его браузер каждые 10 секунд будет "долбить" сервер запросами. Готов ли сервер к такому?

Длинные опросы

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

Схема:

  1. Отправляется запрос на сервер.
  2. Соединение не закрывается сервером, пока не появится сообщение.
  3. Когда сообщение появилось -- сервер отвечает на запрос, пересылая данные.
  4. Браузер тут же делает новый запрос.

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

Схема коммуникации:

При этом если соединение рвётся само, например, из-за ошибки в сети, то браузер тут же отсылает новый запрос.

Примерный код клиентской части:

function subscribe(url) {
  var xhr = new XMLHttpRequest();

  xhr.onreadystatechange = function() {
    if (this.readyState != 4) return;

    if (this.status == 200) {
      onMessage(this.responseText);
    } else {
      onError(this);
    }

    subscribe(url);
  }
  xhr.open("GET", url, true);
  xhr.send();
}

Функция subscribe делает запрос, при ответе обрабатывает результат, и тут же запускает процесс по новой.

Сервер, конечно же, должен уметь работать с большим количеством таких "ожидающих" соединений.

Демо: чат

Демо:

[codetabs src="longpoll" height=500]

Область применения

Длинные опросы отлично работают в тех случаях, когда сообщения приходят редко.

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

В этих случаях используются другие способы получения данных, подразумевающие непрерывное соединение с сервером. Мы рассмотрим их в следующих главах.