Вопрос по – Как Facebook, Gmail отправляют уведомления в режиме реального времени?

260

Я прочитал несколько постов на эту тему, и ответы на них - комета, обратный ajax, потоковое вещание http, загрузка сервера и т. Д.

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

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

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

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

Ваш Ответ

5   ответов
415

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

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

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

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

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

Implementing:

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

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

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

echo json_encode(get_events());
  • The has_event_happened function would just check if anything had happened in an events table or something, and then the get_events function would return a list of the new rows in the table? Depends on the context of the problem really.

  • Don't forget to change your PHP max execution time, otherwise it will timeout early!

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

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

Тем не менее, плагин, кажется, добавляет немного сложности, он действительно очень прост для клиента, возможно (с 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
});

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

Error: User Rate Limit Exceeded Billy
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
18

Согласнослайд-шоу о системе обмена сообщениями FacebookFacebook использует технологию комет, чтобы «подтолкнуть» сообщение для веб-браузеров. Кометный сервер Facebook построен на открытом веб-сервере Erlang с открытым исходным кодом mochiweb.

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

System overview

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

Ты можешь попробоватьicomet, кометный сервер C1000K C ++, созданный с 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 и т. д.

Error: User Rate Limit Exceeded
5

Одна важная проблема с длинным опросом - обработка ошибок. Есть два типа ошибок:

  1. The request might timeout in which case the client should reestablish the connection immediately. This is a normal event in long polling when no messages have arrived.

  2. A network error or an execution error. This is an actual error which the client should gracefully accept and wait for the server to come back on-line.

The main issue is that if your error handler reestablishes the connection immediately also for a type 2 error, the clients would DOS the server.

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

function longPoll() { 
        var shouldDelay = false;

        $.ajax({
            url: 'poll.php',
            async: true,            // by default, it's 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
5

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

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

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

Error: User Rate Limit Exceededdeveloper.android.com/google/gcm/index.htmlError: User Rate Limit Exceeded
39

Update

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


У меня недавно была та же самая проблема и исследовал предмет.

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

Long Polling - Client

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

function pollTask() { 

    $.ajax({

        url: '/api/Polling',
        async: true,            // by default, it's 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):

In jQuery 1.4.x and below, the XMLHttpRequest object will be in an invalid state if the request times out; accessing any object members may throw an exception. In Firefox 3.0+ only, script and JSONP requests cannot be cancelled by a timeout; the script will run even if it arrives after the timeout period.

Long Polling - Server

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

function handleRequest () {  

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

     return events();

} 

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

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

Solution

Используйте розетки!

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

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

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

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

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Как вы думаете, 1 является заменой для другого или есть необходимость в обеих технологиях в одном проекте?
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы