Skip to content
 

Захват флага, или проблема AJAX-запросов к CMS

Представьте ситуацию - для того чтобы узнать, не пришло ли письмо, нужно пойти на почту, отстоять в огромной очереди - и лишь для того чтобы в тысячный раз услышать ответ "для вас ничего нет". Абсурд? В реальном мире - да, а вот в компьютерном - привычная норма! Все чаты, информаторы об обновлениях и прочие подобные сервисы работают именно таким образом: периодически идет запрос к серверу, для выполнения которого загружается фреймворк, строит список сообщений - и убедившись, что номер последней записи совпадает с тем номером, что сейчас последний у клиента, формирует ответ "для вас ничего нет". Казалось бы - ну и ладно, комп железный и пусть трудится, но тут основная проблема - время выполнения. Ведь если клиент проверяет обновления каждую секунду, а сервер выполняет такой запрос за (допустим) 20мс - что очень и очень хорошо  для тяжелых CMS - то одновременно в чате смогут быть не более 50 человек! Действительно, 50 раз по 20мс это как раз одна секунда, и соответственно полная загрузка сервера... Увеличить число клиентов в таких условиях можно только увеличением числа серверов.

Неужели ситуация безвыходна?

Если протокол не дает возможности информировать клиента об изменениях, может хотя бы можно избежать очереди? Например, применив схему абонентских ящиков на почте - клиент приходит и проверяет только свой ящик?

Мной был разработан плагин для WordPress, реализующий эту идею: в файловой системе создается дерево флагов для всех ожидающих события клиентов, которые отдаются как статика и сервер не нагружают. По наступлению события флаг устанавливается, и клиент выполняет запрос к ЦМС для получения данных. Это позволило уменьшить нагрузку на сервер более чем в 20 раз (!), то есть один сервер теперь может выполнять работу двух стоек, забитых серверами :)

Обращение к статическому флагу занимает несколько миллисекунд, и только микросекунды серверного времени - так что количество одновременных пользователей ограничивает теперь не сервер, а ширина канала на передачу HTTP- запросов. При канале 100мбит и размере запроса 1кб это составит около десяти тысяч одновременных пользователей - а теперь сравните с ранее полученным ограничением в 50 пользователей :)

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

Для примера - процесс доработки плагина buddypress-activity-stream-ajax-notifier для использования флагов.

1. В фильтр, вешаемый на событие "wp_print_scripts", перед вызовом wp_localize_script, добавляем вызов

$params['url'] = flags_register_flag('bpactivity_ajax'); //регистрируем флаг для текущего юзера, на выходе - его УРЛ

2. Добавляем установку флага по наступлению события - появлению новой записи активности

add_action('bp_activity_add',function(){
flags_set_flag('bpactivity_ajax'); //установим флаг для всех ожидающих юзеров
});

3. в AJAX-обработчик (функцию etivite_bp_activity_ajax_process_ajax_check_newactivity) добавляем сброс обслуженного флага для текущего юзера

flags_clear_flag('bpactivity_ajax');

4. и заключительный момент - заменяем в JavaScript УРЛ аякс-вызова на сгенерированный URL

// $.get( ajaxurl, {

$.get( BPAA.url, {

Готово!

Итак, всего 4 правки - и снижение нагрузки на сервер более чем на порядок - неплохо, не так ли?

Также можно почитать:

  1. Установка мягких силиконовых пыльников

Один комментарий

  1. Михаил (Екатеринбург) пишет:

    Отзыв: Thumb up 0 Thumb down 0

    Да...и  правда  очень  даже  ОЧЕНЬ !!! )))))

Написать отзыв