Ruby on Rails アプリケーション用の開発サーバーをセットアップするという問題全体が私を混乱させています。WEBrick、Mongrel、Passenger、Apache、Nginx など、他にもたくさんあるはずですが、それらが果たすさまざまな役割を私はよく理解していません。
最初は WEBrick を使い始めましたが、現在は開発に Mongrel を使用しています。これらのサーバーはスタンドアロンですか、それとも Apache の前に配置されていますか?
Passenger について読んだことがありますが、それが何なのかよくわかりません。サイトには「Ruby Web アプリケーションの展開が簡単になります」と書かれていますが、これは Mongrel に代わるものでしょうか? 同じく Web アプリケーションを展開する Capistrano のようなものでしょうか?
SSL をテストしたいのですが、mongrel ではサポートされていないと思います。最適な開発サーバー設定は何でしょうか?
ありがとう
ベストアンサー1
「デプロイメント」という言葉は、文脈に応じて 2 つの意味を持つことがあります。また、Apache/Nginx の役割と他のコンポーネントの役割を混同しています。
歴史的注記: この記事は元々、Ruby アプリケーション サーバーのエコシステムが限られていた 2010 年 11 月 6 日に執筆されました。2013 年 3 月 15 日に、エコシステムの最新の更新をすべて反映してこの記事を更新しました。
免責事項: 私は、アプリケーション サーバーの 1 つである Phusion Passenger の作者の 1 人です。
Apache 対 Nginx
どちらも Web サーバーです。静的ファイルを提供できますが、適切なモジュールを使用すれば、PHP で記述された動的な Web アプリも提供できます。Apache の方が人気があり、機能も豊富です。一方、Nginx はサイズが小さく、高速ですが、機能は少なくなっています。
Apache も Nginx も、そのままでは Ruby Web アプリを提供することはできません。そのためには、後述する何らかのアドオンと組み合わせて Apache/Nginx を使用する必要があります。
Apache と Nginx はリバース プロキシとしても機能します。つまり、受信した HTTP リクエストを、HTTP を話す別のサーバーに転送できます。そのサーバーが HTTP 応答を返すと、Apache/Nginx は応答をクライアントに転送します。これがなぜ重要なのかについては、後で説明します。
Mongrel とその他のプロダクション アプリケーション サーバーと WEBrick の比較
Mongrel は Ruby の「アプリケーション サーバー」です。具体的には、Mongrel は次の機能を備えたアプリケーションです。
- Ruby アプリを独自のプロセス空間内に読み込みます。
- TCP ソケットを設定し、外部 (インターネットなど) と通信できるようにします。Mongrel はこのソケットで HTTP リクエストをリッスンし、リクエスト データを Ruby Web アプリに渡します。
- 次に、Ruby Web アプリは、HTTP 応答がどのようになるかを表すオブジェクトを返します。Mongrel はそれを実際の HTTP 応答 (実際のバイト) に変換し、ソケット経由で送り返します。
しかし、Mongrel はかなり古く、現在ではメンテナンスされていません。新しい代替アプリケーション サーバーは次のとおりです。
- フュージョンパッセンジャー
- ユニコーン
- 薄い
- プーマ
- トリニダード (JRuby のみ)
- TorqueBox (JRuby のみ)
これらについては後ほど取り上げ、それぞれがどのように異なるのか、また Mongrel とどのように異なるのかを説明します。
WEBrick は Mongrel と同じことを行いますが、違いは次のとおりです。
- WEBrick は、私が前に述べた他のすべてのものとは異なり、本番環境には適していません。WEBrick は完全に Ruby で書かれています。Mongrel (および他のほとんどの Ruby アプリケーション サーバー) は一部が Ruby、一部が C (ほとんどが Ruby) ですが、その HTTP パーサーはパフォーマンスを考慮して C で書かれています。
- WEBrick は速度が遅く、堅牢性も低いです。メモリ リークや HTTP 解析の問題がいくつかあることが知られています。
- WEBrick は Ruby にデフォルトで含まれているため、通常は開発中にのみデフォルト サーバーとして使用されます。Mongrel やその他のアプリケーション サーバーは別途インストールする必要があります。何らかの理由で Heroku が WEBrick をデフォルト サーバーとして選択したにもかかわらず、本番環境で WEBrick を使用することは推奨されません。以前は Thin を使用していたため、なぜ WEBrick に切り替えたのかはわかりません。
アプリサーバーと世界
現在のすべての Ruby アプリケーション サーバーは HTTP に対応していますが、一部のアプリケーション サーバーはポート 80 で直接インターネットに公開されている一方、他のアプリケーション サーバーは公開されていない場合があります。
- インターネットに直接公開できるアプリサーバー: Phusion Passenger、Rainbows
- インターネットに直接公開されない可能性のあるアプリケーション サーバー: Mongrel、Unicorn、Thin、Puma。これらのアプリケーション サーバーは、Apache や Nginx などのリバース プロキシ Web サーバーの背後に配置する必要があります。
- Trinidad と TorqueBox についてはよくわからないので省略しました。
一部のアプリケーション サーバーをリバース プロキシの背後に配置する必要があるのはなぜですか?
- 一部のアプリケーション サーバーは、プロセスごとに同時に 1 つのリクエストしか処理できません。2 つのリクエストを同時に処理する場合は、それぞれが同じ Ruby アプリケーションを提供する複数のアプリケーション サーバー インスタンスを実行する必要があります。このアプリケーション サーバー プロセスのセットは、アプリケーション サーバー クラスターと呼ばれます(したがって、Mongrel Cluster、Thin Cluster などと呼ばれます)。次に、このクラスターへのリバース プロキシとして Apache または Nginx を設定する必要があります。Apache/Nginx は、クラスター内のインスタンス間でリクエストを分散します (詳細については、「I/O 同時実行モデル」のセクションを参照してください)。
- Web サーバーはリクエストと応答をバッファリングできるため、アプリケーション サーバーを「低速クライアント」 (データの送受信が遅い HTTP クライアント) から保護できます。クライアントが完全なリクエストを送信したり、完全な応答を受信したりするのを待っている間、アプリケーション サーバーが何もしない状態は避けてください。その間、アプリケーション サーバーは他の処理を実行できない可能性があります。Apache と Nginx は、マルチスレッドまたはイベント処理であるため、同時に多くの処理を実行するのに非常に優れています。
- ほとんどのアプリケーション サーバーは静的ファイルを提供できますが、特に優れているわけではありません。Apache と Nginx はより高速に実行できます。
- 通常、Apache/Nginx は静的ファイルを直接提供するように設定されますが、静的ファイルに対応しないリクエストはアプリケーション サーバーに転送されます。これはセキュリティ上の優れた方法です。Apache と Nginx は非常に成熟しており、アプリケーション サーバーを (おそらく悪意のある) 破損したリクエストから保護できます。
一部のアプリケーション サーバーがインターネットに直接公開されるのはなぜですか?
- Phusion Passenger は、他のすべてのアプリケーション サーバーとはまったく異なります。そのユニークな機能の 1 つは、Web サーバーに統合されることです。
- Rainbows の作者は、これをインターネットに直接公開しても安全であると公に述べています。作者は、HTTP パーサー (および類似のもの) に脆弱性がないことをほぼ確信しています。それでも、作者は保証を提供しておらず、使用は自己責任であると述べています。
アプリケーションサーバーの比較
このセクションでは、これまで言及したほとんどのアプリケーション サーバーを比較しますが、Phusion Passenger は比較しません。Phusion Passenger は他のものとはまったく異なるため、専用のセクションを設けました。Trinidad と TorqueBox については、十分に理解していないため省略しましたが、いずれにしても、これらは JRuby を使用する場合にのみ関係します。
- Mongrelは非常に基本的なものでした。前述のように、Mongrel は純粋なシングルスレッドのマルチプロセスなので、クラスターでのみ役立ちます。プロセス監視はありません。クラスター内のプロセスがクラッシュした場合 (たとえば、アプリのバグが原因)、手動で再起動する必要があります。Monit や God などの外部プロセス監視ツールを使用する傾向があります。
- Unicornは Mongrel のフォークです。限定的なプロセス監視をサポートしています。プロセスがクラッシュすると、マスター プロセスによって自動的に再起動されます。プロセスごとに個別のソケットを使用する代わりに、すべてのプロセスが単一の共有ソケットでリッスンするようにできます。これにより、リバース プロキシの構成が簡素化されます。Mongrel と同様に、純粋にシングル スレッドのマルチプロセスです。
- Thin は、EventMachine ライブラリを利用して、イベント化された I/O モデルを使用します。Mongrel HTTP パーサーを使用する以外は、Mongrel に基づいていません。クラスター モードにはプロセス監視がないため、クラッシュなどを監視する必要があります。Unicorn のような共有ソケットがないため、各プロセスは独自のソケットをリッスンします。理論上、Thin の I/O モデルでは高い同時実行が可能ですが、Thin が使用されるほとんどの実際の状況では、1 つの Thin プロセスで処理できる同時要求は 1 つだけなので、クラスターが必要です。この特殊なプロパティの詳細については、「I/O 同時実行モデル」セクションを参照してください。
- Pumaも Mongrel からフォークされましたが、Unicorn とは異なり、Puma は純粋にマルチスレッドとして設計されています。そのため、現時点では組み込みのクラスター サポートはありません。複数のコアを利用できるように特別な注意を払う必要があります (詳細については、「I/O 同時実行モデル」のセクションを参照してください)。
- Rainbows は、さまざまなライブラリを使用することで複数の同時実行モデルをサポートします。
フュージョンパッセンジャー
フュージョンパッセンジャー他のものとはまったく異なる動作をします。Phusion Passenger は Apache または Nginx に直接統合されるため、Apache の mod_php に相当します。mod_php によって Apache が PHP アプリケーションを魔法のように提供できるようになるのと同様に、Phusion Passenger によって Apache (および Nginx!) が Ruby アプリケーションを魔法のように提供できるようになります。Phusion Passenger の目標は、できるだけ手間をかけずにすべてが Just Work(tm) できるようにすることです。
アプリのプロセスまたはクラスターを開始し、Apache/Nginx を設定して静的ファイルを提供するか、Phusion Passenger を使用してプロセス/クラスターへのリクエストをリバース プロキシする代わりに、次の操作を行うだけで済みます。
- Web サーバーの構成ファイルを編集し、Ruby アプリの「public」ディレクトリの場所を指定します。
- ステップ2はありません。
すべての構成は、Web サーバーの構成ファイル内で行われます。Phusion Passenger は、ほぼすべてを自動化します。クラスターを起動してプロセスを管理する必要はありません。プロセスの開始/停止、クラッシュ時の再起動など、すべて自動化されています。他のアプリ サーバーと比較すると、Phusion Passenger には可動部分がはるかに少なくなっています。この使いやすさが、人々が Phusion Passenger を使用する主な理由の 1 つです。
また、他のアプリ サーバーとは異なり、Phusion Passenger は主に C++ で記述されているため、非常に高速です。
また、エンタープライズバリアント自動ローリング再起動、マルチスレッド サポート、デプロイメント エラー耐性などのさらに多くの機能を備えた Phusion Passenger です。
上記の理由から、Phusion Passenger は現在最も人気のある Ruby アプリケーション サーバーであり、New York Times、Pixar、Airbnb などの大規模な Web サイトを含む 150,000 を超える Web サイトで利用されています。
Phusion Passengerと他のアプリサーバーの比較
Phusion Passenger は、他のアプリ サーバーに比べて、次のような多くの機能と利点を備えています。
- トラフィックに基づいてプロセス数を動的に調整します。リソースが制限されたサーバーでは、公開されていない大量の Rails アプリを実行しており、組織内のユーザーが 1 日に数回しか使用していません。Gitlab、Redmine などです。Phusion Passenger は、使用されていないプロセスを停止し、使用されているときに起動することで、より重要なアプリにリソースを割り当てることができます。他のアプリ サーバーでは、すべてのプロセスが常にオンになっています。
- 一部のアプリケーションサーバーは、設計上、特定のワークロードには適していません。たとえば、Unicornは高速に実行されるリクエストのみを対象として設計されています。ユニコーンのウェブサイト「場合によってはさらに悪化する」セクション。
Unicorn が苦手とするワークロードは次のとおりです。
- ストリーミング ワークロード (例: Rails 4 ライブ ストリーミングまたは Rails 4 テンプレート ストリーミング)。
- アプリが HTTP API 呼び出しを実行するワークロード。
ハイブリッドI/Oモデルフュージョン パッセンジャー エンタープライズ 4またはそれ以降のバージョンでは、このような種類のワークロードに最適です。
- 他のアプリケーション サーバーでは、ユーザーはアプリケーションごとに少なくとも 1 つのインスタンスを実行する必要があります。対照的に、Phusion Passenger は 1 つのインスタンスで複数のアプリケーションをサポートします。これにより、管理オーバーヘッドが大幅に削減されます。
- 自動ユーザー切り替え、便利なセキュリティ機能。
- Phusion Passenger は、多くの MRI Ruby、JRuby、Rubinius をサポートしています。Mongrel、Unicorn、Thin は MRI のみをサポートしています。Puma も 3 つすべてをサポートしています。
- Phusion Passenger は、実際には Ruby 以外のものもサポートしています。Python WSGI もサポートしているため、たとえば Django や Flask アプリも実行できます。実際、Phusion Passenger は多言語サーバーになる方向に向かっています。Node.js のサポートは ToDo リストに載っています。
- 帯域外ガベージ コレクション。Phusion Passenger は、通常のリクエスト/レスポンス サイクルの外で Ruby ガベージ コレクターを実行できるため、リクエスト時間を数百ミリ秒短縮できる可能性があります。Unicorn にも同様の機能がありますが、Phusion Passenger のバージョンの方が柔軟性が高く、1) GC に限定されず、任意の作業に使用できます。2) Phusion Passenger のバージョンはマルチスレッド アプリでうまく機能しますが、Unicorn のバージョンはそうではありません。
- 自動化されたローリング再起動。Unicorn やその他のサーバーでのローリング再起動には、スクリプト作業が必要です。Phusion Passenger Enterprise は、この方法を完全に自動化します。
他にも機能や利点はありますが、リストは本当に長いです。包括的なPhusion Passengerマニュアルを参照してください(Apache バージョン、Nginx バージョン) またはPhusion Passengerのウェブサイト詳細については。
I/O同時実行モデル
- シングルスレッド マルチプロセス。これは、Ruby アプリケーション サーバーで伝統的に最も人気のある I/O モデルです。これは、Ruby エコシステムでのマルチスレッド サポートが非常に貧弱だったことが一因です。各プロセスは、一度に 1 つのリクエストだけを処理できます。Web サーバーはプロセス間で負荷分散を行います。このモデルは非常に堅牢で、プログラマーが同時実行バグを導入する可能性はほとんどありません。ただし、I/O 同時実行は非常に制限されています (プロセス数によって制限されます)。このモデルは、高速で短時間実行されるワークロードに非常に適しています。HTTP API の呼び出しを含むワークロードなど、低速で長時間実行されるブロッキング I/O ワークロードにはまったく適していません。
- 純粋なマルチスレッド。現在、Ruby エコシステムは優れたマルチスレッド サポートを備えているため、この I/O モデルは非常に実現可能になっています。マルチスレッドでは高い I/O 同時実行が可能になるため、短時間実行と長時間実行の両方のブロッキング I/O ワークロードに適しています。プログラマーが同時実行バグを持ち込む可能性は高くなりますが、幸いなことに、ほとんどの Web フレームワークは、これが非常に起こりにくいように設計されています。ただし、注意すべき点の 1 つは、グローバル インタープリター ロック (GIL) を使用しているため、複数のスレッドがある場合でも MRI Ruby インタープリターは複数の CPU コアを活用できないことです。各プロセスは CPU コアを活用できるため、複数のマルチスレッド プロセスを使用することでこれを回避できます。JRuby と Rubinius には GIL がないため、1 つのプロセスで複数のコアを完全に活用できます。
- ハイブリッド マルチスレッド マルチプロセス。主に Phusion Passenger Enterprise 4 以降で実装されています。シングルスレッド マルチプロセス、純粋なマルチスレッド、または複数のスレッドを持つ複数のプロセスを簡単に切り替えることができます。このモデルは、両方の長所を生かします。
- イベント化。このモデルは、前述のモデルとはまったく異なります。非常に高い I/O 同時実行が可能なので、長時間実行されるブロッキング I/O ワークロードに最適です。これを利用するには、アプリケーションとフレームワークからの明示的なサポートが必要です。ただし、Rails や Sinatra などの主要なフレームワークはすべて、イベント化コードをサポートしていません。そのため、実際には Thin プロセスは一度に 1 つ以上のリクエストを処理できず、実質的にシングルスレッドのマルチプロセス モデルと同じように動作します。Cramp など、イベント化 I/O を利用できる特殊なフレームワークがあります。
Phusionブログに最近、ワークロードに応じてプロセスとスレッドの数を最適に調整する方法に関する記事が掲載されました。Phusion Passenger の同時実行設定の調整。
カピストラノ
Capistrano はまったく別のものです。これまでのすべてのセクションで、「デプロイメント」とは、アプリケーション サーバーで Ruby アプリケーションを起動して訪問者がアクセスできるようにする行為を指しますが、その前に通常、次のような準備作業を行う必要があります。
- Ruby アプリのコードとファイルをサーバー マシンにアップロードします。
- アプリが依存するライブラリをインストールします。
- データベースの設定または移行。
- Sidekiq/Resque ワーカーなど、アプリが依存する可能性のあるデーモンを起動および停止します。
- アプリケーションをセットアップするときに実行する必要があるその他の作業。
Capistrano のコンテキストでは、「デプロイ」とは、このすべての準備作業を行うことを指します。Capistrano はアプリケーション サーバーではありません。代わりに、すべての準備作業を自動化するツールです。Capistrano にサーバーの場所と、アプリの新しいバージョンをデプロイするたびに実行する必要があるコマンドを伝えると、Capistrano が Rails アプリをサーバーにアップロードし、指定したコマンドを実行します。
Capistrano は常にアプリケーション サーバーと組み合わせて使用されます。アプリケーション サーバーを置き換えるものではありません。逆に、アプリケーション サーバーは Capistrano を置き換えるものではなく、Capistrano と組み合わせて使用できます。
もちろん、Capistrano を使用する必要はありません。Rubyアプリを FTP でアップロードし、毎回同じコマンドの手順を手動で実行したい場合は、そうすることができます。他の人はそれにうんざりしているので、Capistrano でそれらの手順を自動化しています。