Tue 22 Aug 2006
Варианты настройки Ruby On Rails на максимальную производительность: mongrel vs lighttpd vs nginx
Posted by Scoundrel under Admin-tips , Development , Networks ·
Из-за возможных ошибок в методике тестирования приведенные результаты могут быть не корректными. Потому бяло принято решение провести тестирование заново с измененными параметрами и набором тестов. Новые результаты тестирования Вы можете получить в серии статей “В Поисках Оптимального Решения” и в статье, описывающей результаты всей серии тестов.
На этой неделе мы начали проект, использующий 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
Сравнительные результаты тестирования Вы можете увидеть на следующей дианрамме:
Что же, я сделал свой выбор - я буду использовать nginx для проксирования запросов к кластеру Mongrel-серверов, так как это рещение является очень гибким и обладает прекрасной производительностью.
Если у Вас есть какие-либо предложения по расширению тестирования или замечания к результатам представленных тестов, оставляйте комментарии ниже и я постараюсь ответить на все вопросы. До встречи!
- HAProxy - Надежный, высокопроизводительный балансировщик нагрузки для TCP/HTTP
- Using Nginx, SSI and Memcache to Make Your Web Applications Faster
- В поисках оптимального решения: Ruby On Rails и Mongrel
- 32bit VS 64bit - what do you use?
- В Поисках Оптимального Решения: Результаты Тестирования и Выводы
August 22nd, 2006 at 6:01 am
Hello, Alex
Thanks for useful article. But I have a question: where is the apache (2.0 and 2.2 with mod_balancer)? Why you haven’t tested it?
August 22nd, 2006 at 6:15 am
Ошибка в статье.
> Как и ожидалось, результаты оказались лучше, чем с одним процессом mongrel:
Это про pen. А насколько я вижу, результаты оказались хуже.
August 22nd, 2006 at 6:35 am
Исправил. Вот что значит - тестить днем, а писать и переводить ночью.
August 22nd, 2006 at 6:37 am
> Вот что значит - тестить днем, а писать и переводить ночью.
Бывает.
А почему не было тестов через FastCGI? Так что, медленнее, чем через HTTP?
August 22nd, 2006 at 6:38 am
Сорри за такое количество комментов, еще хотелось узнать - а как это дело всё запускается? Писанный руками скрипт в init.d, или какой-то более удобный метод?
А то руками скрипты ломает писать.
August 22nd, 2006 at 6:41 am
nginx - у меня где-то уже готовый срипт есть.
mongrel - через скрипт + mongrel-cluster.
August 22nd, 2006 at 7:28 am
> WEBrick (веб-сервер, написанный полностью на ruby и включенный в состав rails framework)
WEBrick включен в дистрибутив ruby , в rails - только скрипт его запуска .
Присоединяюсь к вопросу - а где же apache ?
В общем и целом статья понравилась , спасибо.
August 22nd, 2006 at 7:33 am
Насчет апача… Скажу честно - меня, как админа, видавшего апач много раз и в разных позах, сама мысль о том, что он как-то себя покажет в области проксирования сильно смущает… я попробовал поставить 2.2, но он тупо завалился при компиляции с синтакс еррором в области mod_load_balancer или как его там… дальше я не пробовал - НЕ ВЕРЮ! (с) и все тут…
Если общественность настоит - могу попробовать еще раз - для большей полноты картины
August 22nd, 2006 at 7:38 am
Насчёт апача - +1. Не верю, что он может достичь скоростей lighttpd/nginx.
Но мой вопрос остался без ответа - почему не FastCGI, почему монгрел?
August 22nd, 2006 at 7:46 am
А не пробовал увеличивать количество mongrel listners? Думаю для 4x Xeon оптимально будет 8 процессов + nginx.
August 22nd, 2006 at 7:52 am
ошибка: “Вот и все, что необЗодимо.”
коммент потом можно удалить
August 22nd, 2006 at 8:58 am
Кстати, померял скорость проксирования Apache 2.0/Mongrel и Apache 2.0/pen/Mongrel-cluster (5).
Как и ожидалось, результат почти одинаковый (второй вариант дал 5% рост производительности).
Ну же, Леха, когда будут результаты тестирования Apache 2.2 с load balancer’ом?
А вот на 2.2 посмотреть я не прочь
August 22nd, 2006 at 9:11 am
Кстати, дебиановцы 2.2 уже включили в experimental, так что ждем его в скором времени в unstable
http://lists.debian.org/debian-apache/2006/08/msg00053.html
August 22nd, 2006 at 9:38 am
2Alexander Solovyov:
Я попробовал запустить бенчмарк для FastCGI. Машинка слабенькая - 500 селерон, 512 RAM, но mongrel 1000 запросов отрабатывает относительно шустро (104.550197 seconds).
В общем эсперимент был сорван чрезвычайно низкой производительностью FastCGI. Я подождал полчаса, пока оно дошло до 300 реквестов, и на этом закончилось терпение
August 22nd, 2006 at 9:52 am
> низкой производительностью FastCGI.
Хмм… Надо бы с django поэкспериментировать, может у неё что-то подобное тоже есть? :\
August 22nd, 2006 at 12:36 pm
> В общем эсперимент был сорван чрезвычайно низкой производительностью FastCGI. Я подождал полчаса, пока оно дошло до 300 реквестов, и на этом закончилось терпение
Вы его готовить не умеете: у меня на cel-400 c apache1+FastCGI было около 10 req/s
August 22nd, 2006 at 12:42 pm
Может забыли перебить в .htaccess редирект с dispatrch.cgi на dispatch.fcgi?
August 22nd, 2006 at 2:15 pm
где фастцги, вопрошаю я, где?
August 22nd, 2006 at 3:32 pm
What about pound [ http://apsis.ch/pound/ ]? We are using it with good results. Is the nginx better/faster than pound?
August 22nd, 2006 at 3:35 pm
Notice: I’m going to review results of these tests and add some additional solutions like FastCGI with Lighttpd, Apache, nginx and pound server. So, stay tuned!
August 22nd, 2006 at 4:42 pm
Thanks for doing the benchmarks. But I have one big question. What exactly are you testing here? Arew you just hitting the default welcome to rails page of a fresh new rails app? It seems that way to me. So I think your tests are flawed because they are measuring a static html file and not a dynamic rails request. You shou7ld at least set up a hello world controller/action that does at least a siumnple db select query to really test the performance of rails. I seriously doubt that you can get almost 1000 req/sec with a dynamic rails page. It is in the range of what you can expect for static pages but for dynamic pages with at least one db query you will more likely get somewhere around 90-130req/sec. Can you run your tests again against a real rails request? When you just test a staic file, rails does not even get invoked so you are not really testing rails at all.
August 22nd, 2006 at 4:52 pm
2Ezra: Hmmm… I’ve tested on simple start page… Thanks for comment - I will redo all tests and will post results in next blog article.
August 22nd, 2006 at 5:01 pm
Cool. I wasn’t aware of nginx before I saw your post so I am very interested in it. I downloaded it and I will play with it myself also. Thank you!
August 22nd, 2006 at 5:10 pm
Alexander Borovsky: нет, не забыл. именно dispatcher.fcgi
August 22nd, 2006 at 5:16 pm
Alexey- would you mind emailing me so we could have a discussion about nginx? I am writing a book about rails deployment and I am very excited to learn of this project. I would love to work with you to get the optimal setup for running rails with nginx/mongrel and nginx/fastcgi. Would you please contact me so we could discuss more? I think you should have my email already from the comment form. Thank you for your time.
August 22nd, 2006 at 5:17 pm
hello
thanks for this post, i did not knew about nginx.
you might want to chechk out fcgi it is faster than fastcgi
i thought i would use mongrel or lightpd but apache + fcgi was faster (for http://sprinj.com at least)
August 22nd, 2006 at 7:05 pm
Hi,
Just a typo notice:
The title says lihgttpd instead of lighttpd.
August 22nd, 2006 at 11:15 pm
I have another question regarding nginx. Is there a way to set it up for use with rails so that it will first check for static files and then if it doesn not find a file it will invoke the proxy to the backend to get the request? This is how rails page caching works. So if an url like example.com/foo/bar was to be requested, nginx would look for /foo/bar.html and serve it directly if it exists but if not exist it would foreward the request to the proxy backend server? Maybe by using a 404 error handler or something? I would be very interested in gettign a nginx config that has nginx serving all static and page cached files and then forwarding any other requests to a cluster of mongrels via the proxy.
Thanks for mentioning nginx, I have been playiung with it today and I like it very much so far.
August 23rd, 2006 at 12:40 am
2Ezra: yeah. You can create such setup for nginx. You can use rewrite module in following way:
server { root /path/to/your/public; location / { if (!-f $request_filename.html) { # your proxy configuration ... ... } rewrite (.*) $1.html last; } location ~ \.html { #dummy location for static files } }August 23rd, 2006 at 12:55 am
Very cool Alexey. I think nginx is my new favorite front for rails apps. I’m not sure exactly what the dummy location for static files does? Can you explain? Also does this setup automatically serve images, js and css files as static if they are in the public dir of the rails app? Or do I need to add a location ~ .js and a location ~ .css, etc… ?
I appreciate your help with this.
August 23rd, 2006 at 9:34 am
> I’m not sure exactly what the dummy location for static files does?
There you must define root for cached pages, like:
root /path/to/cache
> Also does this setup automatically serve images, js and css files
No, you must define location like this:
location ~* ^.+\.(jpg|jpeg|gif|css|js)$ {
root /path/to/static;
}
August 23rd, 2006 at 2:56 pm
Как и все удивлен почему FastCGI не тестировался… Касаемо Lighttpd - reverse proxy у него несколько кривой не держит keep-alive что я думаю и является причиной тормозов в данном случае.
August 23rd, 2006 at 5:55 pm
Хмм… Да, кстати, насчёт keep-alive, заметка на будущее тестирование: статические файлы надо бы сервить отдельно самим фронтендом, без бэк-ендов. Так и быстрее будет, и keep-alive влиять не будет.
August 25th, 2006 at 7:18 am
Hi,
great blog-entry
Please can you also add HAProxy to your tests
http://haproxy.1wt.eu/
— advertisment from homepage
.
.
HAProxy is a free, very fast and reliable solution offering high availability, load balancing, and proxying for TCP and HTTP-based applications. It is particularly suited for web sites crawling under very high loads while needing persistence or Layer7 processing. Supporting tens of thousands of connections is clearly realistic with todays hardware. Its mode of operation makes its integration into existing architectures very easy and riskless, while still offering the possibility not to expose fragile web servers to the Net.
.
.
—
August 25th, 2006 at 8:21 am
[...] While I’ve been doing performance testing of different Ruby on Rails deployment schemes, I came across very interesting software - HAProxy. HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high availability environments. Indeed, it can : - route HTTP requests depending on statically assigned cookies ; - spread the load among several servers while assuring server persistence through the use of HTTP cookies ; - switch to backup servers in the event a main one fails ; - accept connections to special ports dedicated to service monitoring ; - stop accepting connections without breaking existing ones ; - add/modify/delete HTTP headers both ways ; - block requests matching a particular pattern ; [...]
August 26th, 2006 at 4:58 pm
We would love to see LiteSpeed, http://www.litespeedtech.com. Our 2.2 in-addition to our Ruby LSAPI is one of the top performing platforms for Rail deployment.
August 26th, 2006 at 5:17 pm
2xing: I would be glad to add your software to next benchmark, but I can’t get trial version from your site… there is some error after trial download form… If you want, you can send me archive with trial version by email and I will test it.
August 26th, 2006 at 5:30 pm
2Scoundrel: We have fixed the trial form error. Please try to download the enterprise edition trial key once more. Thanks.
August 26th, 2006 at 6:19 pm
2xing: no luck…
But no mail… so, resend it to me manually, please.
August 28th, 2006 at 3:20 am
Wow I’ve got my license key for LiteSpeed! Will test it now…
August 28th, 2006 at 8:29 am
[...] Aftrer my previous post about high-performance RoR deployment methods, I’ve got lots of messages/emails/IM conversations about some errors in previous benchmarks and there were lots of suggestions about extending of tested software set and modifying testing methodology. So, that is why I decided to perform deep and wide performance testing for all deployment schemes I can find. In this article you can find description of testing methodology and, of course, benchmarks results. If you want to know details of specific software setup, take a look at articles in category “Ruby On Rails” to find all articles from “Looking for optimal Solution” series (I’ll post all of them in next few days). [...]
September 25th, 2006 at 3:58 pm
[...] High-Performance Ruby On Rails Setups Test: mongrel vs lighttpd vs nginx [...]
October 4th, 2006 at 2:30 am
[...] Obviously, this thing is powering 90k domains on the internet with benchmarks showing that it handles more requests per second (as high as 900+ on a single machine) than any other set up. I know that one benchmark doesn’t form substantial evidence but I think nginx will be something to pay attention to in the future (especially for shared hosts that can get taken down by rogue rails apps). [...]
December 20th, 2006 at 6:58 pm
Another question concerning nginx. Since it has been installed I can not figure out how to set php.ini values such as upload_max_size. Is there a specific way to go about configuring these settings? There is no php.ini file in the path now being reported in phpinfo()
December 20th, 2006 at 7:22 pm
2Mark:
Try such command and you’ll see where php tries to find its configs.
February 12th, 2007 at 5:22 pm
[...] “High-Performance Ruby On Rails Setups Test: mongrel vs lighttpd vs nginx” and many other nginx articles by Alexey N. Kovyrin [...]
March 22nd, 2007 at 12:31 pm
Thanks for your benchmarks! You can also use httperf to get speed tests.
July 5th, 2007 at 6:09 am
There’s a little difference in your setup, lighttpd has accesslogs on while nginx doesn’t. I guess that should make a bit of a difference, no?
July 6th, 2007 at 4:39 am
2Thomas: strange, nginx always has really flexible and pretty convenient logging system.
September 14th, 2007 at 6:17 am
Thomas means enabled logs on lighttpd may and probably will make things slower compared to nginx running without logging.
September 19th, 2007 at 3:38 am
Mongrel еще поддерживает фреймверк IOWA
September 27th, 2007 at 5:04 am
[...] http://blog.kovyrin.net/2006/08/22/high-performance-rails-nginx-lighttpd-mongrel/ [...]
November 7th, 2007 at 6:30 am
[...] Rails 应用,有的评测性能已经超过 lighty。Nginx 能快速响应静态页面的请求,支持 [...]
December 6th, 2007 at 6:58 pm
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
December 20th, 2007 at 11:17 pm
[...] High-Performance Ruby On Rails Setups Test: mongrel vs lighttpd vs nginx :: Homo-Adminus Blog by Ale… (tags: rails performance mongrel lighttpd nginx rubyonrails ruby) [...]
January 14th, 2008 at 7:20 am
[...] server has nginx installed there (frontend) and Rails-based application deployed like described in one of my previous posts or in other people’s posts on the net (nginx+mongrel). So, nginx proxies your request to one [...]
March 11th, 2008 at 12:43 am
[...] EDIT: dimenticavo il riferimento a chi ha ispirato questo… post(?)… test(?)… studio(?)… va bhe: http://blog.kovyrin.net [...]