Параметры сервера Ruby on Rails
===============================

Вся проблема настройки сервера разработки для моего приложения Ruby on Rails меня смущает. Есть WEBrick, Mongrel, Passenger, Apache, Nginx и многие другие, я уверен, и я действительно не понимаю разные роли, которые они играют.

Я начал использовать WEBrick, и теперь я использую Mongrel для разработки. Являются ли эти серверы автономными или они сидят перед Apache?

Я прочитал о Пассажире, и я действительно не понимаю, что это такое, сайт говорит, что "делает развертывание веб-приложений Ruby легким", заменит ли он Mongrel? Это похоже на Capistrano, который также развертывает веб-приложения?

Принимая во внимание, что я хотел бы протестировать SSL, и я считаю, что не поддерживается mongrel, какова лучшая настройка сервера разработки?

Спасибо

 

Слово "развертывание" может иметь два значения в зависимости от контекста. Вы также смешиваете роли Apache/Nginx с ролями других компонентов.

Историческая заметка: Эта статья была первоначально написана 6 ноября 2010 года, когда экосистема сервера приложений Ruby была ограничена. Я обновил эту статью 15 марта 2013 года со всеми последними обновлениями в экосистеме.

  **Отказ от ответственности**. Я являюсь одним из авторов Phusion Passenger, одного из серверов приложений.

 Apache vs Nginx
----------------

Они оба являются веб-серверами. Они могут обслуживать статические файлы, но - с правильными модулями - могут также обслуживать динамические веб-приложения, например. написанных на PHP. Apache более популярен и имеет больше возможностей, Nginx меньше и быстрее и имеет меньше возможностей.

Ни Apache, ни Nginx не могут работать с веб-приложениями Ruby из коробки, чтобы сделать это, вам нужно использовать Apache/Nginx в сочетании с каким-то надстройкой, описанным ниже.

Apache и Nginx также могут выступать в качестве обратных прокси, что означает, что они могут принимать входящий HTTP-запрос и перенаправлять его на другой сервер, который также говорит HTTP. Когда этот сервер отвечает HTTP-ответом, Apache/Nginx перенаправляет ответ клиенту; Позже вы узнаете, почему это актуально.

 Mongrel и другие серверы приложений производства против WEBrick
----------------------------------------------------------------

Mongrel - это сервер приложений Ruby. В конкретных терминах это означает, что Mongrel - это приложение, которое:

* Загружает ваше приложение Ruby в собственное пространство процесса.
* Устанавливает TCP-сокет, позволяя ему взаимодействовать с внешним миром (например, Интернет).
Mongrel прослушивает HTTP-запросы в этом сокете и передает данные запроса в веб-приложение Ruby.
* Затем веб-приложение Ruby возвращает объект, который описывает, как должен выглядеть HTTP-ответ, и Mongrel позаботится о преобразовании его в фактический HTTP-ответ (фактические байты) и отправит его обратно через сокет.

Однако Монгрель довольно устарел, в настоящее время он больше не поддерживается. Новые альтернативные серверы приложений:

* Phusion Passenger
* Unicorn
* Тонкий
* Puma
* Тринидад (только JRuby)
* TorqueBox (только JRuby)

Я расскажу им позже и расскажу, как они отличаются друг от друга и от Монгреля.

WEBrick делает то же самое, что и Mongrel, но различия заключаются в следующем:

* WEBrick не подходит для производства, в отличие от всего остального, о котором я упоминал ранее. WEBrick полностью написан на Ruby. Mongrel (и большинство других серверов приложений Ruby) является частью Ruby и частью C (Mostly Ruby), но его HTTP-парсер написан на C для производительности.
* WEBrick работает медленнее и менее надежно. Он имеет некоторые известные утечки памяти и некоторые известные проблемы разбора HTTP.
* WEBrick обычно используется только как сервер по умолчанию во время разработки, потому что WEBrick по умолчанию включен в Ruby. Mongrel и другие серверы приложений должны быть установлены отдельно. Не рекомендуется использовать WEBrick в производственных средах, хотя по какой-то причине Heroku выбрал WEBrick в качестве сервера по умолчанию. Раньше они использовали Thin, поэтому я понятия не имею, почему они переключились на WEBrick.

 Сервер приложений и мир
------------------------

Все текущие серверы приложений Ruby говорят на HTTP, однако некоторые серверы приложений могут быть напрямую открыты для Интернета на порту 80, а другие - нет.

* Серверы приложений, которые могут быть напрямую доступны в Интернете: Phusion Passenger, Rainbows
* Серверы приложений, которые не могут быть напрямую открыты для Интернета: Mongrel, Unicorn, Thin, Puma. Эти серверы приложений должны быть размещены за сервером обратного прокси-сервера, таким как Apache и Nginx.
* Я не знаю достаточно о Trinidad и TorqueBox, поэтому я их опустил.

Почему серверы приложений должны быть помещены за обратный прокси?

* Некоторые серверы приложений могут обрабатывать только один запрос одновременно, за каждый процесс. Если вы хотите одновременно обрабатывать 2 запроса, вам нужно запустить несколько экземпляров сервера приложений, каждый из которых обслуживает одно и то же приложение Ruby. Этот набор процессов сервера приложений называется кластером серверов приложений (отсюда и название Mongrel Cluster, Thin Cluster и т.д.). Затем вы должны настроить Apache или Nginx для обратного прокси-сервера для этого кластера. Apache/Nginx позаботится о распределении запросов между экземплярами в кластере (подробнее об этом в разделе "Модели ввода/вывода concurrency" ).
* Веб-сервер может буферизовать запросы и ответы, защищая сервер приложений от "медленных клиентов" - HTTP-клиенты, которые не отправляют или принимают данные очень быстро. Вы не хотите, чтобы ваш сервер приложений ничего не делал, ожидая, когда клиент отправит полный запрос или получит полный ответ, потому что в течение этого времени сервер приложений, возможно, не сможет ничего сделать. Apache и Nginx очень хорошо делают много вещей одновременно, потому что они либо многопоточные, либо событиями.
* Большинство серверов приложений могут обслуживать статические файлы, но не особенно хороши в этом. Apache и Nginx могут делать это быстрее.
* Люди обычно настраивают Apache/Nginx для непосредственного использования статических файлов, но перенаправляют запросы, которые не соответствуют статическим файлам на сервер приложений, это хорошая практика безопасности. Apache и Nginx очень зрелы и могут защитить сервер приложений от (возможно, злонамеренных) поврежденных запросов.

Почему некоторые серверы приложений могут быть напрямую открыты для Интернета?

* Phusion Passenger - совсем другой зверь из всех других серверов приложений. Одна из его уникальных особенностей заключается в том, что он интегрируется в веб-сервер.
* Автор Rainbows публично заявил, что безопасно напрямую выставлять его в Интернет. Автор уверен, что уязвимости в парсере HTTP (и аналогичном) отсутствуют. Тем не менее, автор не дает никаких гарантий и говорит, что использование на свой страх и риск.

 Сравнение серверов приложений
------------------------------

В этом разделе я сравню большинство серверов приложений, о которых я упомянул, но не Phusion Passenger. Phusion Passenger - это такой отличный зверь из остальных, что я дал ему выделенный раздел. Я также пропустил Trinidad и TorqueBox, потому что я не знаю их достаточно хорошо, но они имеют значение только в том случае, если вы используете JRuby.

* **Mongrel** был довольно голыми. Как упоминалось ранее, Mongrel является чисто однопоточным многопроцессом, поэтому он полезен только в кластере. Мониторинг процесса отсутствует: если процесс в кластере аварийно завершается (например, из-за ошибки в приложении), его необходимо перезапустить вручную. Люди склонны использовать внешние инструменты мониторинга процессов, такие как Монит и Бог.
* **Единорог** - это вилка Монгреля. Он поддерживает ограниченный мониторинг процесса: при сбое процесса он автоматически перезапускается мастер-процессом. Он может заставить все процессы прослушивать один общий сокет вместо отдельного сокета для каждого процесса. Это упрощает конфигурацию обратного прокси. Подобно Mongrel, это чисто однопоточный многопроцессор.
* **Тонкий** использует модель ввода-вывода с использованием библиотеки EventMachine. Помимо использования парсера Mongrel HTTP, он никоим образом не основан на Mongrel. В режиме кластера нет мониторинга процесса, поэтому вам необходимо отслеживать сбои и т.д. Единый универсальный сокет не существует, поэтому каждый процесс прослушивает его собственный сокет. Теоретически, модель Тонкого ввода-вывода допускает высокий concurrency, но в большинстве практических ситуаций, в которых используется Thin, один тонкий процесс может обрабатывать только один одновременный запрос, поэтому вам по-прежнему нужен кластер. Подробнее об этом своеобразном свойстве в разделе "Модели ввода-вывода concurrency".
* **Puma** также был разветвлен у Mongrel, но в отличие от Unicorn, Puma спроектирован как чисто многопоточный. Поэтому в настоящее время нет встроенной поддержки кластеров. Вы должны проявлять особую осторожность, чтобы убедиться, что вы можете использовать несколько ядер (подробнее об этом в разделе "Модели ввода/вывода concurrency" ).
* **Rainbows** поддерживает несколько моделей concurrency с использованием разных библиотек.

 Phusion Passenger
------------------

 [Phusion Passenger](https://www.phusionpassenger.com) работает совсем не так, как у всех остальных. Phusion Passenger интегрируется непосредственно в Apache или Nginx, и поэтому его можно сравнить с mod\_php для Apache. Точно так же, как mod\_php позволяет Apache обслуживать приложения PHP, почти волшебным образом, Phusion Passenger позволяет Apache (а также Nginx!) Работать с приложениями Ruby почти волшебным образом. Цель Phusion Passenger состоит в том, чтобы сделать все Just Work (tm) максимально возможной проблемой.

Вместо запуска процесса или кластера для вашего приложения и настройки Apache/Nginx для обслуживания статических файлов и/или обратных прокси-запросов к процессу/кластеру с помощью Phusion Passenger вам нужно только:

* Вы редактируете файл конфигурации веб-сервера и указываете местоположение своего общедоступного каталога приложения Ruby.
* Нет шага 2.

Вся конфигурация выполняется в конфигурационном файле веб-сервера. Phusion Passenger автоматизирует практически все. Нет необходимости запускать кластер и управлять процессами. Запуск/остановка процессов, перезапуск их при сбое и т.д. - все автоматизировано. По сравнению с другими серверами приложений, у Phusion Passenger гораздо меньше движущихся частей. Эта простота использования является одной из основных причин, почему люди используют Phusion Passenger.

Кроме того, в отличие от других серверов приложений, Phusion Passenger в основном написан на С++, что делает его очень быстрым.

Существует также [Enterprise variant](https://www.phusionpassenger.com/enterprise) от Phusion Passenger с еще большим количеством функций, таких как автоматическая перезагрузка, поддержка многопоточности, устойчивость к ошибкам развертывания и т.д.

По вышеуказанным причинам Phusion Passenger в настоящее время является самым популярным сервером приложений Ruby, который включает более 150 000 веб-сайтов, включая такие крупные, как New York Times, Pixar, Airbnb и т.д.

 Phusion Passenger и другие серверы приложений
----------------------------------------------

Phusion Passenger предоставляет намного больше возможностей и предоставляет множество преимуществ по сравнению с другими серверами приложений, такими как:

* Динамическая настройка количества процессов на основе трафика. Мы запускаем тонну приложений Rails на нашем ограниченном ресурсами сервере, которые не являются публичными, и что люди в нашей организации используют не более нескольких раз в день. Такие вещи, как Gitlab, Redmine и т.д. Phusion Passenger может отжимать эти процессы, когда они не используются, и разворачивать их, когда они используются, что позволяет использовать больше ресурсов для более важных приложений. С другими серверами приложений все ваши процессы включаются все время.
* Некоторые серверы приложений не подходят для определенных рабочих нагрузок, по дизайну. Например, Unicorn предназначен только для быстрых запросов: см. [сайт Unicorn](http://unicorn.bogomips.org/PHILOSOPHY.html) в разделе "Хуже того, в некоторых случаях".

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

* Потоковые рабочие нагрузки (например, потоковая передача Rails 4 или потоковая передача Rails 4).
* Рабочая нагрузка, при которой приложение выполняет вызовы API HTTP.

Модель гибридного ввода-вывода в [Phusion Passenger Enterprise 4](https://www.phusionpassenger.com/enterprise) или более поздняя версия делает ее отличным выбором для этих видов рабочих нагрузок.

* Другие серверы приложений требуют от пользователя запускать хотя бы один экземпляр для каждого приложения. В отличие от этого, Phusion Passenger поддерживает несколько приложений в одном экземпляре. Это значительно снижает административные издержки.
* Автоматическое переключение пользователей, удобная функция безопасности.
* Phusion Passenger поддерживает множество MRI Ruby, JRuby и Rubinius. Mongrel, Unicorn и Thin поддерживают только МРТ. Puma также поддерживает все 3.
* Phusion Passenger фактически поддерживает больше, чем просто Ruby! Он также поддерживает Python WSGI, поэтому он может, например, запускать приложения Django и Flask. Фактически, Phusion Passenger движется в направлении становления полиглот-сервера. Node.js в списке задач.
* Внеполосная сборка мусора. Phusion Passenger может запускать сборщик мусора Ruby за пределами обычного цикла запроса/ответа, что потенциально сокращает время запроса на сотни миллисекунд. У Единорога также есть аналогичная функция, но версия Phusion Passenger более гибкая, потому что
1) он не ограничивается GC и может использоваться для произвольной работы.
2) Версия Phusion Passenger хорошо работает с многопоточными приложениями, а Unicorn - нет.
* Автоматическая перезагрузка. Перезапуск на Unicorn и другие серверы требуют некоторых скриптовых работ. Phusion Passenger Enterprise полностью автоматизирует этот путь для вас.

Есть больше возможностей и преимуществ, но список действительно длинный. Вы должны обратиться к руководству полного руководства Phusion Passenger ([версия Apache](http://www.modrails.com/documentation/Users%20guide%20Apache.html), [версия Nginx](http://www.modrails.com/documentation/Users%20guide%20Nginx.html)) или [веб-сайт Phusion Passenger](https://www.phusionpassenger.com) для информации.

 Модели ввода/вывода concurrency
--------------------------------

* **Однопоточный многопроцессор.**Это традиционно самая популярная модель ввода-вывода для серверов приложений Ruby, частично потому, что поддержка многопоточности в экосистеме Ruby была очень плохой. Каждый процесс может обрабатывать ровно 1 запрос за раз. Нагрузка веб-сервера выравнивается между процессами. Эта модель очень надежная, и у программиста мало шансов ввести ошибки concurrency. Однако его ввод/вывод concurrency чрезвычайно ограничен (ограничен количеством процессов). Эта модель очень подходит для быстрых и коротких рабочих нагрузок. Он очень непригоден для медленных, длительных блокирующих рабочих нагрузок ввода-вывода, например. рабочих нагрузок, связанных с вызовом HTTP API.
* **Чисто многопоточное.** В настоящее время экосистема Ruby обладает отличной поддержкой многопоточности, поэтому эта модель ввода-вывода стала очень жизнеспособной. Многопоточность обеспечивает высокий уровень ввода-вывода concurrency, что делает его подходящим как для коротких, так и для длительных рабочих нагрузок ввода-вывода. Программист с большей вероятностью представит ошибки concurrency, но, к счастью, большинство веб-фреймворков разработаны таким образом, что это все еще маловероятно. Следует отметить, однако, что интерпретатор MRI Ruby не может использовать несколько ядер процессора даже в случае нескольких потоков из-за использования Global Interpreter Lock (GIL). Вы можете обойти это, используя несколько многопоточных процессов, потому что каждый процесс может использовать ядро ЦП. JRuby и Rubinius не имеют GIL, поэтому они могут полностью использовать несколько ядер в одном процессе.
* **Гибридный многопоточный многопроцессор.**. В первую очередь реализовано Phusion Passenger Enterprise 4 и более поздними версиями. Вы можете легко переключаться между однопоточными многопроцессорными, чисто многопоточными или, возможно, даже несколькими процессами с несколькими потоками. Эта модель дает лучшее из обоих миров.
* **Событие.**. Эта модель полностью отличается от ранее упомянутой модели. Он обеспечивает очень высокий уровень ввода-вывода concurrency и, следовательно, отлично подходит для длительной блокировки рабочих нагрузок ввода-вывода. Чтобы использовать его, требуется явная поддержка приложения и рамки. Тем не менее, все основные структуры, такие как Rails и Sinatra, не поддерживают код события. Вот почему на практике тонкий процесс по-прежнему не может обрабатывать более одного запроса за раз, что делает его эффективным, как однопоточная мультипроцессная модель. Существуют специализированные структуры, которые могут использовать возможности ввода-вывода, такие как Cramp.

Недавно в блоге Phusion была опубликована статья о оптимальной настройке количества процессов и потоков с учетом вашей рабочей нагрузки. См. [Настройка параметров Phusion Passenger concurrency](http://blog.phusion.nl/2013/03/12/tuning-phusion-passengers-concurrency-settings/).

 Capistrano
-----------

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

* Загрузка кода приложения и файлов Ruby на серверную машину.
* Установка библиотек, от которых зависит ваше приложение.
* Настройка или миграция базы данных.
* Запуск и остановка любых демонов, на которые может положиться ваше приложение, таких как работники Sidekiq/Resque или что-то еще.
* Любые другие действия, которые необходимо выполнить при настройке вашего приложения.

В контексте Капистрано "развертывание" означает выполнение всей этой подготовительной работы. Capistrano не является сервером приложений. Вместо этого это инструмент для автоматизации всей этой подготовительной работы. Вы скажете Capistrano, где находится ваш сервер, и какие команды нужно запускать каждый раз при развертывании новой версии вашего приложения, а Capistrano позаботится о том, чтобы загрузить приложение Rails на сервер и выполнить указанные вами команды.

Capistrano всегда используется в сочетании с сервером приложений. Он не заменяет серверы приложений. И наоборот, серверы приложений не заменяют Capistrano, их можно использовать в сочетании с Capistrano.

Конечно, вам не нужно использовать Capistrano. Если вы предпочитаете загружать свое приложение Ruby с FTP и вручную запускать одинаковые действия с командами каждый раз, вы можете это сделать. Другие люди устали от этого, поэтому они автоматизируют эти шаги в Капистрано.