Pull to refresh

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

Reading time3 min
Views11K
Здравствуйте, хабралюди. Сегодня я хочу рассказать о том, как в одном из наших проектов мы снизили количество запросов на сервер на пару порядков за счет использования технологии 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а. Райану Бейтсу респект и уважуха.
Tags:
Hubs:
+39
Comments25

Articles

Change theme settings