Варианты настройки Ruby On Rails на максимальную производительность: mongrel vs lighttpd vs nginx

Posted by Alexey Kovyrin under Admin-tips, Development, Networks · english

Из-за возможных ошибок в методике тестирования приведенные результаты могут быть не корректными. Потому бяло принято решение провести тестирование заново с измененными параметрами и набором тестов. Новые результаты тестирования Вы можете получить в серии статей “В Поисках Оптимального Решения” и в статье, описывающей результаты всей серии тестов.

На этой неделе мы начали проект, использующий Ruby on Rails как основное средство разработки. Моей первоочередной задачей являлась настройка окружения на одном из наших development-серверов. Когда я попытался разобраться, как же другие люди запускают и используют RoR, я заметил, что в Internet нет информации о настройке rails-приложений в связке с nginx frontend и нет информации о производительности такого решения. Перед тем, как вслепую выбирать решение для хостинга нового проекта я решил провести небольшое тестирование популярных решений для запуска Rails-приложений. Результаты этих тестов и конфигурационные файлы, использованные при тестировании, вы можете увидеть в этой статье.

В первую очередь, опишу программную и аппаратную составляющие тестового сервера:

  • CPU: 4 x XEON CPUs
  • Memory: 4 Gb of RAM
  • OS: Debian GNU/Linux Testing с последним ядром 2.6

Далее в статье будут приведены конфигурации, использованные в тестах и результаты, полученные при помощи apache benchmarking tool (ab).
В конце статьи я приведу сравнительные итоги тестирования в виде диаргаммы. Все тесты выполнялись при помощи следующей комманды:

$ ab -c 100 -n 10000 http://127.0.0.1:PORT/

где PORT – это специфичный для каждого теста номер порта, на котором слушает веб-сервер.

Первым среди тестов я опишу решение с использованием простого сервера WEBrick (веб-сервер, написанный полностью на ruby и включенный в состав rails framework). Для его запуска я использовал следующую команду:

$ ./script/server --port 8080 -d

Результаты этого теста оказались впечатляющими для меня. Я ожидал, что Webrick должен быть очень медленным, но он показал далеко не нулевые результаты ;-) .

  • Web Server: WEBrick/1.3.1
  • Время, затраченное на тесты: 51.490
  • Средняя продолжительность запроса: 514.896
  • Время, затраченное на запрос (среднее по всем параллельным запросам): 5.149
  • Количество запросов в секунду (среднее): 194,21
  • Transfer rate (Kbytes/sec): 1478,88

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

Следующий тест был проведен для Mongrel:

Mongrel – это быстрая HTTP-библиотека и веб-сервер для Ruby, предназначенные для хостинга веб-приложений на Ruby используя HTTP вместо FastCGI или SCGI. На данный момент он поддерживает фреймворки Ruby On Rails, Og+Nitro и Camping.

Самый простой метод начать использование Mongrel – это установить его с помощью RubyGems и затем запускать с его помощью приложения Ruby on Rails. Вы можете сделать это просто:

$ sudo gem install mongrel
$ cd your_rails_app
$ mongrel_rails start -d

Этот набор команд запустит Mongrel в фоне. Вы можете остановить его:

$ mongrel_rails stop

Вот и все, что необзодимо. Есть еще несколько опций, которые могут быть установлены у команды start. Используйте mongrel_rails start -h для просмотра возможных опций и их описания.

Мой тест Mongrel был произведен на одном процессе, запущенном следующим образом:

$ mongrel_rails start -d --port 8081

Результаты оказались следующими:

  • Web Server: Mongrel 0.3.13.3 (single process)
  • Время, затраченное на тесты: 17.212
  • Средняя продолжительность запроса: 172.117
  • Время, затраченное на запрос (среднее по всем параллельным запросам): 1.721
  • Количество запросов в секунду (среднее): 581,00
  • Transfer rate (Kbytes/sec): 4398,28

Как видите, Mongrel действительно значительно быстрее по сравнению с сервером WEBrick, но давайте посмотрим, что могут показать нам другие сервера.

Третий тест был выполнен при помощи простого tcp-балансировщика (pen) и 5 рабочих процессов Mongrel. Pen был установлен из репозитория debian, потому инсталляция прошла просто (apt-get install pen). Тест проводился при помощи процесса pen, запущенного следующей командой:

$ pen 8082 127.0.0.1:3000 \\
           127.0.0.1:3001 \\
           127.0.0.1:3002 \\
           127.0.0.1:3003 \\
           127.0.0.1:3004

В процессе тестирования я запускал процессы mongrel при помощи самописного скрипта на shell, но позже я наткнулся на mongrel-cluster – GemPlugin, котороый работает с mongrel и сильно упрощает настройку и установку веб-приложений, используя кластер mongrel-серверов. Если вы захотите повторить тесты или воспользоваться их результатами – используйте его для упрощения процесса настройки.

Как и ожидалось, результаты оказались лучше, чем в первом тесте, но, что странно, хуже, чем в тесте с одним процессом mongrel:

  • Web Server: Mongrel 0.3.13.3 (5 процессов через балансировщик Pen )
  • Время, затраченное на тесты: 19.864
  • Средняя продолжительность запроса: 198.642
  • Время, затраченное на запрос (среднее по всем параллельным запросам): 1.986
  • Количество запросов в секунду (среднее): 503,42
  • Transfer rate (Kbytes/sec): 3810,98

Следующие два теста проводились с использованием двух популярных reverse-proxy серверов: Nginx и Lighttpd с теми же пятью процессами Mongrel.

Первым протестированным сервером был Lighttpd, собранный следующими командами:

# ./configure --prefix=/opt/lighttpd
# make
# make install

Следующий конфигурационный файл был использован для запуска lighttpd:

server.modules              = (
                                "mod_access",
                                "mod_proxy",
                                "mod_accesslog"
                              )

server.document-root        = "/opt/lighttpd/www/"
server.errorlog             = "/opt/lighttpd/logs/lighttpd.error.log"
index-file.names            = ( "index.htm" )

server.tag                 = "lighttpd"
accesslog.filename          = "/opt/lighttpd/logs/access.log"
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

server.port                = 8083
server.pid-file            = "/var/run/lighttpd.pid"

proxy.balance = "fair"

proxy.server  = (
  "/" =>
     ( ( "host" => "127.0.0.1", "port" => 3000 ),
       ( "host" => "127.0.0.1", "port" => 3001 ),
       ( "host" => "127.0.0.1", "port" => 3002 ),
       ( "host" => "127.0.0.1", "port" => 3003 ),
       ( "host" => "127.0.0.1", "port" => 3004 )
     )
  )

Результаты оказались намного лучше, чем у всех предщественников:

  • Web Server: Lighttpd 1.4.11 (прокси для 5 процессов Mongrel)
  • Время, затраченное на тесты: 14.256
  • Средняя продолжительность запроса: 142.570
  • Время, затраченное на запрос (среднее по всем параллельным запросам): 1.426
  • Количество запросов в секунду (среднее): 701,41
  • Transfer rate (Kbytes/sec): 5321,53

Из-за странной проблемы авторы mongrel не советуют использовать lighttpd для проксирования, но должен сказать – у меня он заработал нормально.

И последним тестом оказался тест nginx reverse-proxy сервера. Я решил провести этот тест после всех остальных так как не нашел никакой информации о его производительности и хотел показать, как производится его настройка и проверить его производительность с Ruby on Rails когда я уже буду знать все результаты… Итак, я собрал его со стандартными параметрами:

# ./configure --prefix=/opt/nginx
# make
# make install

и проверил со следующим конфигурационным файлом:

worker_processes  2;

error_log  logs/error.log notice;
pid        logs/nginx.pid;

events {
    worker_connections  16384;
}

http {
    include       conf/mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    tcp_nopush     on;

    keepalive_timeout  65;
    tcp_nodelay        on;

    upstream mongrel {
        server 127.0.0.1:3000;
        server 127.0.0.1:3001;
        server 127.0.0.1:3002;
        server 127.0.0.1:3003;
        server 127.0.0.1:3004;
    }

    server {
        listen       8084;
        server_name  localhost;

        access_log  off;

        location / {
            proxy_pass  http://mongrel;
        }
    }
}

Результаты этого теста оказались поистине впечатляющими и я еще раз хочу сказать спасибо Игорю Сысоеву за отличный продукт!

  • Web Server: nginx/0.3.60 (прокси для 5 процессов Mongrel)
  • Время, затраченное на тесты: 10.449
  • Средняя продолжительность запроса: 104.495
  • Время, затраченное на запрос (среднее по всем параллельным запросам): 1.045
  • Количество запросов в секунду (среднее): 956.99
  • Transfer rate (Kbytes/sec): 7267.27

Сравнительные результаты тестирования Вы можете увидеть на следующей дианрамме:
Rails Performance with Different Access Methods

Что же, я сделал свой выбор – я буду использовать nginx для проксирования запросов к кластеру Mongrel-серверов, так как это рещение является очень гибким и обладает прекрасной производительностью. :-)

Если у Вас есть какие-либо предложения по расширению тестирования или замечания к результатам представленных тестов, оставляйте комментарии ниже и я постараюсь ответить на все вопросы. До встречи!


Related posts:

  1. В поисках оптимального решения: Ruby On Rails и Mongrel
  2. HAProxy – Надежный, высокопроизводительный балансировщик нагрузки для TCP/HTTP
  3. Использование Nginx Как Reverse-Proxy Сервера На Загруженных Сайтах
  4. MySQL Performance Blog – Отличный ресурс для администраторов MySQL
  5. Использование lighttpd, Mplayer/Mencoder и Flvtool2 для реализации потоковой раздачи Flash Video

58 Responses to this entry

Ruby Developers says:

Aleksey,

I agree, I believe that Thomas meant that enabling the logs on the Lighttpd would make everything run slower than Nginx without the logs. But isn’t it obvious? If you want faster then you have to unable the logging features.

Jenn

ashes999 says:

Hi,

We’re having some discussion on the RailsRocket forums about the performance of different web-servers. Have you tried the Thin web-server? How does it compare to the rest?