Как стать автором
Обновить

Faye как способ не задолбать свой сервер

Время на прочтение3 мин
Количество просмотров12K
Здравствуйте, хабралюди. Сегодня я хочу рассказать о том, как в одном из наших проектов мы снизили количество запросов на сервер на пару порядков за счет использования технологии Comet.

Суть проблемы: веб-приложение для службы такси, диспетчера работают удаленно (из дома, из офиса и т.п.). Перед каждым — список заказов. Состояние заказов может измениться в любой момент — водитель взял заказ, водитель отказался, клиент отказался, другой диспетчер завел новый заказ. Очень важно чтобы диспетчер видел картину практически в реальном времени, поскольку в час пик звонки идут один за другим без перерыва. Вначале это было сделано через вызывающийся периодически (setTimeout) AJAX запрос, который получив с сервера отрендеренный список текущих запросов заменял содержимое div'а. Для 1-2 разработчиков, и пары тестеров это казалось нормальной идеей — 1-2 запроса в секунду не сильно напрягали. По результатам компромисса между актуальностью и снижением нагрузки на сервер определились что будем дергать сервер раз в 3 секунды.

Однако реальная жизнь быстро расставила все по местам. Во-первых, в реальности в списке заказов не 5-10, а 30-40 одновременно исполняющихся заказов. Во-вторых, диспетчеров около десятка. Нагрузка на сервер уверенно поползла вверх. Мы решили не дожидаться пока с ростом популярности нам положат сервер и переделали обновление списка на основе технологии Comet, а конкретнее — на основе полезного гема faye.

В основе идеи лежит принцип Long Polling — это когда при загрузке страницы яваскрипт делает скрытый AJAX запрос к серверу сообщений, а тот, пока сказать нечего, не отдает ни байта. Далее либо запрос отваливается по таймауту — тогда яваскрипт повторяет запрос, либо в ответ приходит нормальный яваскрипт, который будет выполнен на клиентской стороне.

Использовать гем достаточно просто:
1. Устанавливаем гем faye (дописываем в Gemfile и делаем bundle install)

2. Дописываем
require "net/http"

в config/application.rb

Это нужно чтобы работал хелпер отправки сообщений — наверное, потом интегрируют его в гем, но пока надо руками вписать.

3. Создаем новый файлик с текстом
FAYE_TOKEN = "anything"

Это задает строку, по которой сервер сообщений будет отличать одно приложение от другого, если их станет несколько. Вместо «anything» можно написать что угодно, только чтобы потом не запутаться.

4. Создаем хелпер для отправки сообщений (например, в application_helper.rb)
def broadcast(channel, &block)
message = {:channel => channel, :data => capture(&block), :ext => {:auth_token => FAYE_TOKEN}}
uri = URI.parse("http://moesuperprilozhenie.ru:9292/faye")
Net::HTTP.post_form(uri, :message => message.to_json)
end


Этот хелпер легко потом использовать как-то так в любой вьюшке:
- broadcast "/orders/update" do
$("#orders_list").append("#{escape_javascript render(@orders) }");


5. Создаем файлик в корне проекта, например faye.ru
require 'faye'
require File.expand_path('../config/initializers/faye_token.rb', __FILE__)

class ServerAuth
def incoming(message, callback)
if message['channel'] !~ %r{^/meta/}
if message['ext']['auth_token'] != FAYE_TOKEN
message['error'] = 'Invalid authentication token'
end
end
callback.call(message)
end
end

faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 45)
faye_server.add_extension(ServerAuth.new)
run faye_server


Это — инструкция для запуска Rack сервера Faye, который и будет собственно рассылать обновления клиентам.

6. Запуск сервера сообщений:
rackup faye.ru -s thin -E production


Тут мы запускаем сервер сообщений в соответствии с файлом faye.ru, на базе Web-сервера thin и в режиме production.
Здесь есть тонкий момент — аргумент -E production относится не к окружению Вашего приложения, а к режиму работы самого faye и thin. Если указать -E development — будут глюки, почему не знаю, может починили.

7. В яваскрипте на загрузку страницы:
$(function() {
var faye = new Faye.Client('http://moesuperprilozhenie.ru:9292/faye');
faye.subscribe("/orders/update", function(data) {
eval(data);
});
});


8. Добавить в список подключаемых яваскриптов faye.js (берется прямо с сервера сообщений, в нашем случае — moesuperprilozhenie.ru:9292/faye). Пример на haml:
= javascript_include_tag "http://moesuperprilozhenie.ru:9292/faye.js"


9. Открываем новоприкрученный селектеловский график нагрузки на процессор и радуемся.

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

UPD: Код в статье взят из Railscastа. Райану Бейтсу респект и уважуха.
Теги:
Хабы:
Всего голосов 45: ↑42 и ↓3+39
Комментарии25

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань