Слово «развертывание» может иметь два значения в зависимости от контекста. Вы также путаете роли Apache / Nginx с ролями других компонентов.
Историческая справка. Эта статья была первоначально написана 6 ноября 2010 года, когда экосистема сервера приложений Ruby была ограничена. Я обновил эту статью 15 марта 2013 года всеми последними обновлениями в экосистеме.
Отказ от ответственности : я являюсь одним из авторов Phusion Passenger, одного из серверов приложений.
Апач против 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
- единорог
- тонкий
- пума
- Тринидад (только JRuby)
- TorqueBox (только JRuby)
Я расскажу о них позже и опишу, как они отличаются друг от друга и от беспородных.
WEBrick делает то же самое, что и Mongrel, но различия заключаются в следующем:
- WEBrick не подходит для производства, в отличие от всего, что я упоминал ранее. WEBrick полностью написан на Ruby. Mongrel (и большинство других серверов приложений Ruby) является частью Ruby и частью C (главным образом 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.
- Я не знаю достаточно о Тринидаде и TorqueBox, поэтому я опустил их.
Почему некоторые серверы приложений должны находиться за обратным прокси-сервером?
- Некоторые серверы приложений могут обрабатывать только 1 запрос одновременно для каждого процесса. Если вы хотите обрабатывать 2 запроса одновременно, вам нужно запустить несколько экземпляров сервера приложений, каждый из которых обслуживает одно и то же приложение Ruby. Этот набор процессов сервера приложений называется кластером сервера приложений (отсюда и название Mongrel Cluster, Thin Cluster и т. Д.). Затем вы должны настроить Apache или Nginx для обращения прокси к этому кластеру. Apache / Nginx позаботится о распределении запросов между экземплярами в кластере (подробнее об этом в разделе «Модели параллелизма ввода-вывода»).
- Веб-сервер может буферизовать запросы и ответы, защищая сервер приложений от «медленных клиентов» - HTTP-клиентов, которые не очень быстро отправляют или принимают данные. Вы не хотите, чтобы ваш сервер приложений ничего не делал, ожидая, пока клиент отправит полный запрос или получит полный ответ, потому что в течение этого времени сервер приложений, возможно, больше не сможет ничего делать. Apache и Nginx отлично справляются со многими задачами одновременно, потому что они либо многопоточные, либо четные.
- Большинство серверов приложений могут обслуживать статические файлы, но не особенно хороши в этом. Apache и Nginx могут сделать это быстрее.
- Люди обычно настраивают Apache / Nginx для непосредственного обслуживания статических файлов, но перенаправлять запросы, которые не соответствуют статическим файлам, на сервер приложений, это хорошая практика безопасности. Apache и Nginx очень развиты и могут защитить сервер приложений от (возможно, злонамеренно) поврежденных запросов.
Почему некоторые серверы приложений могут быть напрямую подключены к Интернету?
- Phusion Passenger - это совершенно другой зверь, чем все остальные серверы приложений. Одна из его уникальных особенностей заключается в том, что он интегрируется в веб-сервер.
- Автор Rainbows публично заявил, что безопасно напрямую выставить его в Интернет. Автор вполне уверен, что в парсере HTTP нет уязвимостей (и подобных). Тем не менее, автор не дает никаких гарантий и говорит, что использование на свой страх и риск.
Сравнение серверов приложений
В этом разделе я сравню большинство серверов приложений, которые я упомянул, но не Phusion Passenger. Phusion Passenger настолько отличается от остальных, что я выделил ему специальный раздел. Я также опустил Trinidad и TorqueBox, потому что я не знаю их достаточно хорошо, но они все равно актуальны, если вы используете JRuby.
- Дворняга была довольно голая. Как упоминалось ранее, Mongrel является чисто однопоточным многопроцессорным процессом, поэтому он полезен только в кластере. Мониторинг процессов отсутствует: если происходит сбой процесса в кластере (например, из-за ошибки в приложении), его необходимо перезапустить вручную. Люди склонны использовать внешние инструменты мониторинга процессов, такие как Monit и God.
- Единорог - вилка дворняги. Он поддерживает ограниченный мониторинг процессов: в случае сбоя процесса он автоматически перезапускается главным процессом. Он может заставить все процессы прослушивать один общий сокет вместо отдельного сокета для каждого процесса. Это упрощает настройку обратного прокси. Как и Mongrel, это чисто однопоточный многопроцессорный процесс.
- Thin использует модель четного ввода-вывода, используя библиотеку EventMachine. Кроме использования парсера Mongrel HTTP, он никак не основан на Mongrel. Его кластерный режим не контролирует процессы, поэтому вам нужно отслеживать сбои и т. Д. Не существует Unicorn-подобного общего сокета, поэтому каждый процесс прослушивает свой собственный сокет. Теоретически, модель ввода / вывода Thin допускает высокий уровень параллелизма, но в большинстве практических ситуаций, для которых используется Thin, один процесс Thin может обрабатывать только 1 параллельный запрос, поэтому вам все еще нужен кластер. Подробнее об этом своеобразном свойстве в разделе «Модели параллелизма ввода / вывода».
- Puma также была разветвленной от Mongrel, но в отличие от Unicorn, Puma разработана как чисто многопоточная. Поэтому в настоящее время нет встроенной поддержки кластера. Вы должны проявить особую осторожность, чтобы гарантировать возможность использования нескольких ядер (подробнее об этом в разделе «Модели параллелизма ввода-вывода»).
- Rainbows поддерживает несколько моделей параллелизма за счет использования разных библиотек.
Phusion Passenger
Phusion Passenger работает совсем не так, как все остальные. 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 в основном написан на C ++, что делает его очень быстрым.
Существует также версия Phusion Passenger для предприятий с еще более широкими возможностями, такими как автоматический повторный запуск, поддержка многопоточности, устойчивость к ошибкам развертывания и т. Д.
По вышеуказанным причинам Phusion Passenger в настоящее время является самым популярным сервером приложений Ruby, на котором работают более 150 000 веб-сайтов, включая такие крупные, как New York Times, Pixar, Airbnb и т. Д.
Phusion Passenger против других серверов приложений
Phusion Passenger предоставляет гораздо больше возможностей и предоставляет множество преимуществ по сравнению с другими серверами приложений, такими как:
- Динамическая настройка количества процессов в зависимости от трафика. На нашем сервере с ограниченными ресурсами мы запускаем множество приложений Rails, которые не являются общедоступными, и которые люди в нашей организации используют только несколько раз в день. Такие вещи, как Gitlab, Redmine и т. Д. Phusion Passenger может ускорять эти процессы, когда они не используются, и ускорять их, когда они используются, позволяя получить больше ресурсов для более важных приложений. На других серверах приложений все ваши процессы включены постоянно.
- Некоторые серверы приложений не подходят для определенных рабочих нагрузок. Например, Unicorn предназначен только для быстро выполняющихся запросов: см. Раздел веб-сайта Unicorn «Просто хуже в некоторых случаях».
Рабочие нагрузки, в которых Unicorn не очень хороши:
- Потоковые рабочие нагрузки (например, потоковая передача по Rails 4 или потоковая передача по шаблону Rails 4).
- Рабочие нагрузки, в которых приложение выполняет вызовы HTTP API.
Модель гибридного ввода-вывода в Phusion Passenger Enterprise 4 или более поздней версии делает ее отличным выбором для такого рода рабочих нагрузок.
- Другие серверы приложений требуют, чтобы пользователь запускал хотя бы один экземпляр для каждого приложения. Phusion Passenger, напротив, поддерживает несколько приложений в одном экземпляре. Это значительно снижает накладные расходы администрации.
- Автоматическое переключение пользователей, удобная функция безопасности.
- Phusion Passenger поддерживает множество MRI Ruby, JRuby и Rubinius. Монгрел, Единорог и Тонкий поддерживают только МРТ. Puma также поддерживает все 3.
- Phusion Passenger на самом деле поддерживает не только Ruby! Он также поддерживает Python WSGI, поэтому может, например, запускать приложения Django и Flask. Фактически Phusion Passenger движется в направлении становления сервером полиглота. Поддержка Node.js в списке задач.
- Внеполосный сборщик мусора. Phusion Passenger может запускать сборщик мусора Ruby вне обычного цикла запроса / ответа, что потенциально сокращает время запроса на сотни миллисекунд. Unicorn также имеет аналогичную функцию, но версия Phusion Passenger более гибкая, поскольку 1) она не ограничена GC и может использоваться для произвольной работы. 2) Версия Phusion Passenger хорошо работает с многопоточными приложениями, а Unicorn - нет.
- Автоматическая прокатка перезапусков. Повторный перезапуск на Unicorn и других серверах требует некоторой работы сценариев. Phusion Passenger Enterprise полностью автоматизирует этот путь для вас.
Есть больше возможностей и преимуществ, но список действительно длинный. Вы должны обратиться к всестороннему руководству Phusion Passenger ( версии Apache , Nginx версия ) или на веб - сайт пассажирской Phusion для информации.
Модели параллелизма ввода / вывода
- Однопоточный многопроцессный. Это традиционно самая популярная модель ввода-вывода для серверов приложений Ruby, отчасти потому, что поддержка многопоточности в экосистеме Ruby была очень плохой. Каждый процесс может обрабатывать ровно 1 запрос одновременно. Балансы нагрузки веб-сервера между процессами. Эта модель очень надежна, и у программиста практически нет шансов представить ошибки параллелизма. Однако его параллелизм ввода / вывода чрезвычайно ограничен (ограничен числом процессов). Эта модель очень подходит для быстрых, кратковременных рабочих нагрузок. Это очень непригодно для медленных, длительных блокирующих рабочих нагрузок ввода-вывода, например, рабочих нагрузок, связанных с вызовом HTTP API.
- Чисто многопоточный. В настоящее время экосистема Ruby имеет отличную поддержку многопоточности, поэтому эта модель ввода / вывода стала очень жизнеспособной. Многопоточность обеспечивает высокий параллелизм ввода-вывода, что делает его пригодным как для кратковременных, так и для длительных блокирующих рабочих нагрузок ввода-вывода. Программист более склонен вводить ошибки параллелизма, но, к счастью, большинство веб-фреймворков спроектированы таким образом, что это все еще маловероятно. Однако следует отметить, что интерпретатор Ruby MRI не может использовать несколько ядер ЦП даже при наличии нескольких потоков из-за использования глобальной блокировки интерпретатора (GIL). Вы можете обойти это, используя несколько многопоточных процессов, потому что каждый процесс может использовать ядро процессора. JRuby и Rubinius не имеют GIL, поэтому они могут полностью использовать несколько ядер в одном процессе.
- Гибридный многопоточный многопроцессный. В основном реализовано в Phusion Passenger Enterprise 4 и более поздних версиях. Вы можете легко переключаться между однопоточными многопроцессорными, чисто многопоточными или, возможно, даже несколькими процессами, каждый из которых имеет несколько потоков. Эта модель дает лучшее из обоих миров.
- Evented. Эта модель полностью отличается от ранее упомянутой модели. Он обеспечивает очень высокий уровень параллелизма ввода-вывода и поэтому отлично подходит для длительной блокировки рабочих нагрузок ввода-вывода. Чтобы использовать его, требуется явная поддержка со стороны приложения и инфраструктуры. Однако все основные фреймворки, такие как Rails и Sinatra, не поддерживают четный код. Вот почему на практике процесс Thin по-прежнему не может обрабатывать более 1 запроса за один раз, что делает его фактически таким же, как однопоточная многопроцессорная модель. Существуют специализированные фреймворки, которые могут использовать преимущества четного ввода-вывода, такие как Cramp.
Недавно в блоге Phusion была опубликована статья об оптимальной настройке количества процессов и потоков с учетом вашей рабочей нагрузки. См. Настройка параметров параллелизма Phusion Passenger .
Capistrano
Capistrano - это нечто совершенно другое. Во всех предыдущих разделах «развертывание» относится к процессу запуска приложения Ruby на сервере приложений, так что оно становится доступным для посетителей, но прежде чем это произойдет, обычно необходимо выполнить некоторые подготовительные действия, такие как:
- Загрузка кода и файлов приложения Ruby на сервер.
- Установка библиотек, от которых зависит ваше приложение.
- Настройка или миграция базы данных.
- Запуск и остановка любых демонов, на которые может положиться ваше приложение, таких как работники Sidekiq / Resque или что-то еще.
- Любые другие вещи, которые необходимо выполнить при настройке приложения.
В контексте Capistrano «развертывание» означает выполнение всей этой подготовительной работы. Capistrano не является сервером приложений. Это инструмент для автоматизации всей подготовительной работы. Вы сообщаете Capistrano, где находится ваш сервер и какие команды нужно запускать каждый раз, когда вы развертываете новую версию своего приложения, а Capistrano позаботится о том, чтобы загрузить приложение Rails на сервер и выполнить указанные вами команды.
Capistrano всегда используется в сочетании с сервером приложений. Он не заменяет серверы приложений. Наоборот, серверы приложений не заменяют Capistrano, их можно использовать в сочетании с Capistrano.
Конечно, вам не нужно использовать Capistrano. Если вы предпочитаете загружать приложение Ruby с FTP и вручную каждый раз выполнять одни и те же шаги команд, то вы можете это сделать. Другие люди устали от этого, поэтому они автоматизируют эти шаги в Капистрано.