То, как Facebook делает это, довольно интересно.
Распространенным способом выполнения таких уведомлений является опрос сценария на сервере (с использованием AJAX) в течение заданного интервала (возможно, каждые несколько секунд), чтобы проверить, произошло ли что-то. Однако это может быть довольно интенсивно в сети, и вы часто делаете бессмысленные запросы, потому что ничего не произошло.
То, как Facebook делает это, использует кометный подход, а не опрашивает интервал, как только один опрос завершается, он выдает другой. Однако каждый запрос к сценарию на сервере имеет очень длительное время ожидания, и сервер отвечает на запрос только после того, как что-то произошло. Это может произойти, если вы откроете вкладку «Консоль» Firebug на Facebook, где запросы к сценарию могут занимать минуты. Это действительно гениально, поскольку этот метод сразу сокращает количество запросов и частоту их отправки. Теперь у вас есть структура событий, которая позволяет серверу «запускать» события.
Кроме того, с точки зрения фактического содержимого, возвращаемого этими опросами, это ответ в формате JSON, представляющий собой список событий и информацию о них. Он минимизирован, поэтому его немного сложно прочитать.
С точки зрения современной технологии, AJAX - это путь, потому что вы можете контролировать время ожидания запроса и многое другое. Я бы порекомендовал (клише с переполнением стека) использовать JQuery для выполнения AJAX, это устранит множество проблем с совместимостью. С точки зрения PHP, вы можете просто опрашивать таблицу базы данных журнала событий в своем PHP-сценарии и возвращаться к клиенту только тогда, когда что-то происходит? Я ожидаю, что есть много способов реализовать это.
Реализация:
Сторона сервера:
Кажется, в PHP есть несколько реализаций кометных библиотек, но, честно говоря, это действительно очень просто, что-то вроде следующего псевдокода:
while(!has_event_happened()) {
sleep(5);
}
echo json_encode(get_events());
Функция has_event_happened будет просто проверять, произошло ли что-нибудь в таблице событий или что-то в этом роде, а затем функция get_events выдаст список новых строк в таблице? Зависит от контекста проблемы действительно.
Не забудьте изменить максимальное время выполнения PHP, иначе время ожидания истечет!
Сторона клиента:
Взгляните на плагин 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
});
Все зависит от того, как ваша существующая архитектура собрана воедино.
Обновить
Поскольку я продолжаю получать отзывы об этом, я думаю, что разумно помнить, что этому ответу 4 года. Веб развивался очень быстрыми темпами, поэтому, пожалуйста, помните об этом ответе.
У меня недавно была та же самая проблема и исследовал предмет.
Данное решение называется длинным опросом, и для его правильного использования вы должны быть уверены, что ваш AJAX-запрос имеет «большой» тайм-аут и всегда выполнять этот запрос после окончания текущего (тайм-аут, ошибка или успех).
Длинный опрос - Клиент
Здесь, для краткости кода, я буду использовать jQuery:
Важно помнить, что (из документов jQuery ):
Длинный опрос - сервер
Это не на каком-то конкретном языке, но это будет примерно так:
Здесь
hasTimedOut
убедитесь, что ваш код не ждет вечно, иanythingHappened
проверит, произошло ли какое-либо событие. Предназначенsleep
для освобождения вашей темы, чтобы делать другие вещи, пока ничего не происходит.events
Возвращает словарь событий (или любой другой структуры данных , вы можете предпочесть) в формате JSON (или любой другой вы предпочитаете).Это, безусловно, решает проблему, но, если вы обеспокоены масштабируемостью и производительностью, как я это делал при исследовании, вы могли бы рассмотреть другое решение, которое я нашел.
Решение
Используйте розетки!
На стороне клиента, чтобы избежать проблем совместимости, используйте socket.io . Он пытается использовать сокет напрямую и иметь запасные варианты для других решений, когда сокеты недоступны.
На стороне сервера создайте сервер, используя NodeJS (пример здесь ). Клиент подпишется на этот канал (наблюдатель), созданный на сервере. Всякий раз, когда необходимо отправить уведомление, оно публикуется на этом канале, и подписчик (клиент) получает уведомление.
Если вам не нравится это решение, попробуйте APE ( Ajax Push Engine ).
Надеюсь, я помог.
источник
hasTimedOut()
?Согласно слайд-шоу о системе обмена сообщениями Facebook, Facebook использует технологию комет для « передачи » сообщений в веб-браузеры. Кометный сервер Facebook построен на открытом веб-сервере Erlang mochiweb.
На рисунке ниже фраза «кластеры каналов» означает «серверы комет».
Многие другие крупные веб-сайты создают свой собственный комет-сервер, потому что между потребностями каждой компании есть различия. Но построить свой собственный комет-сервер на комет-сервере с открытым исходным кодом - это хороший подход.
Вы можете попробовать icomet , кометный сервер C1000K C ++, созданный с libevent. icomet также предоставляет библиотеку JavaScript, ее легко использовать так же просто, как:
icomet поддерживает широкий спектр браузеров и операционных систем, включая Safari (iOS, Mac), IE (Windows), Firefox, Chrome и т. д.
источник
Facebook использует MQTT вместо HTTP. Толчок лучше, чем опрос. Через HTTP нам нужно постоянно опрашивать сервер, но через MQTT-сервер отправляет сообщение клиентам.
Сравнение между MQTT и HTTP: http://www.youtube.com/watch?v=-KNPXPmx88E
Примечание: мои ответы лучше всего подходят для мобильных устройств.
источник
Одна важная проблема с длинным опросом - обработка ошибок. Есть два типа ошибок:
Время ожидания запроса может истечь, и в этом случае клиент должен немедленно восстановить соединение. Это нормальное событие при длительном опросе, когда сообщения не поступили.
Ошибка сети или ошибка выполнения. Это фактическая ошибка, которую клиент должен изящно принять и дождаться, пока сервер вернется в оперативный режим.
Основная проблема заключается в том, что если ваш обработчик ошибок немедленно восстанавливает соединение и для ошибки типа 2, клиенты будут DOS сервером.
Оба ответа с примером кода пропускают это.
источник