Как facebook, gmail отправляют уведомление в реальном времени?

Я прочитал несколько сообщений по этой теме, и ответы - это комета, обратный аякс, потоковая передача HTTP, нагрузка на сервер и т.д.

Как работает уведомление о входящей почте в Gmail?

Как GMail Chat может выполнять запросы AJAX без взаимодействия с клиентом?

Я хотел бы знать, есть ли какие-либо ссылки на код, которые я могу выполнить, чтобы написать очень простой пример. Многие сообщения или веб-сайты просто говорят о технологии. Трудно найти полный образец кода. Кроме того, кажется, что многие методы могут быть использованы для реализации кометы, например. Скрытый IFrame, XMLHttpRequest. На мой взгляд, использование XMLHttpRequest - лучший выбор. Что вы думаете о плюсах и минусах разных методов? Какой из них использует Gmail?

Я знаю, что это нужно делать как на стороне сервера, так и на стороне клиента. Есть ли код примера PHP и Javascript?

Ответ 1

То, как Facebook делает это, довольно интересно.

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

То, как Facebook использует метод кометы, а не опрос с интервалом, как только один опрос завершается, он выдает еще один. Однако каждый запрос script на сервере имеет чрезвычайно длительный тайм-аут, и сервер только отвечает на запрос, как только что-то произошло. Вы можете увидеть это, если вы откроете вкладку Firebug Console на Facebook, с запросами на script, возможно, за считанные минуты. Это очень изобретательно, так как этот метод сокращается сразу как по количеству запросов, так и по частоте их отправки. Теперь у вас есть система событий, которая позволяет серверу "запускать" события.

За этим, с точки зрения фактического контента, полученного из этих опросов, это ответ JSON, с тем, что, как представляется, является списком событий, и информацией о них. Он был миниатюрный, так что его немного трудно читать.

С точки зрения реальной технологии AJAX - это путь, потому что вы можете контролировать таймауты запросов и многое другое. Я бы рекомендовал (Qaru cliche здесь) с помощью jQuery, чтобы сделать AJAX, это займёт много проблем кросс-совместимости. Что касается PHP, вы можете просто опросить таблицу базы данных журнала событий в своем PHP script и только вернуться к клиенту, когда что-то произойдет? Есть, я надеюсь, многие способы реализации этого.

Реализация:

Сторона сервера:

В PHP существует несколько реализаций библиотек комет, но, честно говоря, это действительно очень просто, что-то вроде следующего псевдокода:

while(!has_event_happened()) {
   sleep(5);
}

echo json_encode(get_events());
  • Функция has_event_happened проверяет, произошло ли что-либо в таблице событий или что-то в этом роде, а затем функция get_events вернет список новых строк в таблице? Зависит от контекста проблемы.

  • Не забудьте изменить время выполнения PHP max, иначе он будет истекать раньше!

Сторона клиента:

Взгляните на плагин jQuery для взаимодействия с кометами:

Тем не менее, плагин, кажется, добавляет немного сложности, на самом деле это очень просто на клиенте, возможно (с jQuery), что-то вроде:

function doPoll() {
   $.get("events.php", {}, function(result) {
      $.each(result.events, function(event) { //iterate over the events
          //do something with your event
      });
      doPoll(); 
      //this effectively causes the poll to run again as
      //soon as the response comes back
   }, 'json'); 
}

$(document).ready(function() {
    $.ajaxSetup({
       timeout: 1000*60//set a global AJAX timeout of a minute
    });
    doPoll(); // do the first poll
});

Все зависит от того, как ваша существующая архитектура объединяется.

Ответ 2

Обновить

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


Недавно у меня была такая же проблема, и я исследовал эту тему.

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

Лонг-опрос - клиент

Здесь, чтобы сохранить код коротким, я буду использовать jQuery:

function pollTask() { 

    $.ajax({

        url: '/api/Polling',
        async: true,            // by default, it async, but...
        dataType: 'json',       // or the dataType you are working with
        timeout: 10000,          // IMPORTANT! this is a 10 seconds timeout
        cache: false

    }).done(function (eventList) {  

       // Handle your data here
       var data;
       for (var eventName in eventList) {

            data = eventList[eventName];
            dispatcher.handle(eventName, data); // handle the 'eventName' with 'data'

       }

    }).always(pollTask);

}

Важно помнить, что (из jQuery docs):

В jQuery 1.4.x и ниже объект XMLHttpRequest будет находиться в недопустимом состоянии, если время ожидания запроса; доступ к любому члену объекта может вызвать исключение. В Firefox 3. 0+ только сценарии и запросы JSONP не могут быть отменены таймаутом; скрипт будет запущен, даже если он поступит после периода ожидания.

Длительный опрос - сервер

Это не на каком-либо конкретном языке, но это было бы примерно так:

function handleRequest () {  

     while (!anythingHappened() || hasTimedOut()) { sleep(2); }

     return events();

} 

Здесь hasTimedOut гарантирует, что ваш код не будет ждать вечно, и anythingHappened, проверит, hasTimedOut ли какое-либо событие. sleep предназначен для того, чтобы освободить ваш поток, чтобы делать другие вещи, пока ничего не происходит. events возвращают словарь событий (или любую другую структуру данных, которую вы можете предпочесть) в формате JSON (или любой другой, который вы предпочитаете).

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

Решение

Используйте гнезда!

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

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

Если вам не нравится это решение, попробуйте APE (Ajax Push Engine).

Надеюсь, я помог.

Ответ 3

В соответствии с слайд-шоу о системе обмена сообщениями Facebook Facebook использует технологию комет для "push" сообщения для веб-браузеров. Кометный сервер Facebook построен на веб-сервере с открытым исходным кодом Erlang mochiweb.

На рисунке ниже фраза "кластеры каналов" означает "кометные серверы".

System overview

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

Вы можете попробовать icomet, кометный сервер C1000K С++, созданный с libevent. icomet также предоставляет библиотеку JavaScript, ее легко использовать так же просто, как:

var comet = new iComet({
    sign_url: 'http://' + app_host + '/sign?obj=' + obj,
    sub_url: 'http://' + icomet_host + '/sub',
    callback: function(msg){
        // on server push
        alert(msg.content);
    }
});

icomet поддерживает широкий спектр браузеров и ОС, включая Safari (iOS, Mac), IE (Windows), Firefox, Chrome и т.д.

Ответ 4

Facebook использует MQTT вместо HTTP. Push лучше, чем опрос. Через HTTP нам нужно постоянно опросить сервер, но через MQTT-сервер выдает сообщение клиентам.

Сравнение MQTT и HTTP: http://www.youtube.com/watch?v=-KNPXPmx88E

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

Ответ 5

Одной из важных проблем с длинным опросом является обработка ошибок. Существует два типа ошибок:

  • Запрос может иметь таймаут, и в этом случае клиент должен немедленно восстановить соединение. Это нормальное событие при длительном опросе, когда сообщения не поступали.

  • Ошибка сети или ошибка выполнения. Это фактическая ошибка, которую клиент должен изящно принять и ждать, пока сервер вернется в оперативный режим.

Основная проблема заключается в том, что если ваш обработчик ошибок немедленно восстанавливает соединение для ошибки типа 2, клиенты будут DOS-сервером.

Оба ответа с примером кода пропустите это.

function longPoll() { 
        var shouldDelay = false;

        $.ajax({
            url: 'poll.php',
            async: true,            // by default, it async, but...
            dataType: 'json',       // or the dataType you are working with
            timeout: 10000,          // IMPORTANT! this is a 10 seconds timeout
            cache: false

        }).done(function (data, textStatus, jqXHR) {
             // do something with data...

        }).fail(function (jqXHR, textStatus, errorThrown ) {
            shouldDelay = textStatus !== "timeout";

        }).always(function() {
            // in case of network error. throttle otherwise we DOS ourselves. If it was a timeout, its normal operation. go again.
            var delay = shouldDelay ? 10000: 0;
            window.setTimeout(longPoll, delay);
        });
}
longPoll(); //fire first handler