「展開」という言葉は、状況に応じて2つの意味を持つことができます。また、Apache/Nginxの役割と他のコンポーネントの役割を混同しています。
歴史的注:この記事は、2010年11月6日にRubyアプリケーションサーバーのエコシステムが制限されていたときに最初に書かれました。私は2013年3月15日にこの記事を更新し、エコシステムのすべての最新の更新情報を掲載しました。
免責事項:私はPhusion Passengerの作者の一人、アプリサーバーの1人です。
ApacheとNginx
両方ともWebサーバーです。それらは静的ファイルを提供することができますが - 正しいモジュールで - 動的ウェブアプリも提供することができます。 PHPで書かれたものApacheはより人気があり、より多くの機能を持っています。Nginxはより小さくより速く、そしてより少ない機能を持っています。
ApacheもNginxもRubyのWebアプリケーションをそのまま使用することはできません。そのためには、後述するように、何らかのアドオンと組み合わせてApache/Nginxを使用する必要があります。
ApacheとNginxはリバースプロキシとして機能することもできます。つまり、着信HTTPリクエストを受け取り、それを別のサーバーに転送することができます。そのサーバーがHTTP応答で応答すると、Apache/Nginxはその応答をクライアントに転送します。これがなぜ適切なのか、後で学びます。
Mongrelと他のプロダクションアプリサーバー対WEBrick
MongrelはRubyの "アプリケーションサーバー"です。具体的に言うと、Mongrelは以下のようなアプリケーションです。
- あなたのRubyアプリをそれ自身のプロセス空間の中にロードします。
- TCPソケットを設定し、それが外部の世界(例えばインターネット)と通信できるようにします。 MongrelはこのソケットでHTTPリクエストを待ち受け、リクエストデータをRubyウェブアプリに渡します。
- 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に含まれているため、通常WEBrickは開発中のデフォルトサーバとしてのみ使用されます。 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クラスター、シンクラスターなどと呼ばれます)。その後、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 concurrency models"に)。
- Rainbowsは、異なるライブラリを使用して複数の並行性モデルをサポートします。
フュージョンパッセンジャー
Phusion Passenger は他のものとはまったく異なる動作をします。 Phusion PassengerはApacheまたはNginxに直接統合されているため、Apacheのmod_phpと比較できます。 mod_phpがApacheにPHPアプリケーションの提供をほぼ魔法のように許可するのと同様に、Phusion PassengerはApache(およびNginx!)の提供をほぼ魔法のように許可します。 Phusion Passengerの目標は、可能な限り少ない手間でJust Work(tm)をすべて動作させることです。
アプリケーションのプロセスまたはクラスタを起動し、静的ファイルを処理するようにApache/Nginxを設定したり、Phusion Passengerを使用してプロセス/クラスタへの要求を逆プロキシするのではなく、次の手順を実行するだけです。
- Webサーバーの設定ファイルを編集して、あなたのRubyアプリの 'public'ディレクトリの場所を指定します。
- ステップ2はありません。
すべての設定はWebサーバの設定ファイル内で行われます。 Phusion Passengerは、ほとんどすべてを自動化します。クラスタを起動してプロセスを管理する必要はありません。プロセスの起動/停止、クラッシュ時の再起動など - すべて自動化されています。他のアプリサーバーと比べて、Phusion Passengerは可動部品がはるかに少ないです。この使いやすさが、人々がPhusion Passengerを使用する主な理由の1つです。
また、他のアプリサーバーとは異なり、Phusion Passengerは主にC++で書かれているため、非常に高速です。
自動ローリング再起動、マルチスレッドのサポート、デプロイメントのエラー耐性など、さらに多くの機能を備えた Enterprise版 のPhusion Passengerもあります。
上記の理由から、Phusion Passengerは現在最も人気のあるRubyアプリケーションサーバーで、New York Times、Pixar、Airbnbなどの大規模ウェブサイトを含む15万以上のウェブサイトを運営しています。
Phusion Passengerと他のアプリサーバー
Phusion Passengerは他にも多くの機能を提供し、他のアプリサーバーよりも多くの利点を提供します。
- トラフィックに基づいてプロセス数を動的に調整します。私たちは、リソースに制限があるサーバー上で一般向けではないRailsアプリケーションを大量に実行しています。また、組織内のユーザーは1日にせいぜい数回しか使用しません。 Gitlab、Redmineなど。PhusionPassengerは、使用していないときはこれらのプロセスを停止し、使用しているときは起動して、より重要なアプリケーションに使用できるリソースを増やすことができます。他のアプリサーバーでは、すべてのプロセスが常にオンになっています。
- 設計上、一部のアプリサーバーは特定のワークロードに適していません。たとえば、Unicornは高速実行要求専用に設計されています。 nicorn Webサイト 「いくつかのケースではもっと悪い」を参照してください。
Unicornが得意ではないワークロードは次のとおりです。
- ストリーミングワークロード(例:Rails 4ライブストリーミングまたはRails 4テンプレートストリーミング)。
- アプリがHTTP API呼び出しを実行するワークロード。
Phusion Passenger Enterprise 4 以降のハイブリッドI/Oモデルは、このような種類のワークロードに最適な選択肢です。
- 他のアプリケーションサーバーでは、ユーザーはアプリケーションごとに少なくとも1つのインスタンスを実行する必要があります。これとは対照的に、Phusion Passengerは単一のインスタンスで複数のアプリケーションをサポートします。これにより、管理オーバーヘッドが大幅に削減されます。
- 自動ユーザー切り替え、便利なセキュリティ機能。
- Phusion Passengerは多くのMRI Ruby、JRuby、Rubiniusをサポートしています。 Mongrel、Unicorn、ThinはMRIのみをサポートしています。 Pumaも3つすべてをサポートしています。
- Phusion Passengerは実際にはRuby以上のものをサポートしています。 Python WSGIもサポートしているので、例えばDjangoやFlaskアプリも実行できます。実際、Phusion Passengerはポリグロットサーバーになる方向に向かっています。 ToDoリストでのNode.jsのサポート。
- 帯域外ガベージコレクション。 Phusion Passengerは、通常のリクエスト/レスポンスサイクルの外でRubyガベージコレクタを実行することができ、リクエスト時間を数百ミリ秒短縮する可能性があります。 Unicornにも同様の機能がありますが、Phusion Passengerのバージョンは、1)GCに限定されず、任意の作業に使用できるため、より柔軟です。 2)Phusion Passengerのバージョンはマルチスレッドのアプリケーションでうまく機能するが、Unicornのバージョンではそうではない。
- 自動ローリング再起動Unicornや他のサーバーでのローリング再起動には、ある程度のスクリプト作業が必要です。 Phusion Passenger Enterpriseはあなたのためにこの方法を完全に自動化しています。
より多くの機能と利点がありますが、リストは本当に長いです。詳しくは、Phusion Passengerの総合マニュアル( Apacheバージョン 、 Nginxバージョン )または Phusion Passenger Webサイト を参照してください。
入出力並行性モデル
- シングルスレッドマルチプロセスこれは、Rubyアプリケーションサーバー用の伝統的に最も普及しているI/Oモデルです。悪い。各プロセスは一度に1つの要求を処理できます。 Webサーバーはプロセス間で負荷を分散します。このモデルは非常に堅牢であり、プログラマが並行性のバグを引き起こす可能性はほとんどありません。ただし、そのI/O同時実行性は非常に限られています(プロセス数によって制限されています)。このモデルは、高速で短時間のワークロードに非常に適しています。低速で長時間のブロッキングI/Oワークロードにはあまり適していません。 HTTP APIの呼び出しを含むワークロード.
- 純粋なマルチスレッド今日のRubyエコシステムは優れたマルチスレッドサポートを持っているので、このI/Oモデルは非常に実行可能になりました。マルチスレッドを使用すると、高い入出力並行性が可能になるため、短期および長期のブロッキング入出力ワークロードの両方に適しています。プログラマーは並行性のバグを引き起こす可能性が高いですが、幸運にもほとんどのWebフレームワークはこれがまだ非常にありそうもないような方法で設計されています。注意すべき点は、Global Interpreter Lock(GIL)を使用しているため、複数のスレッドがある場合でもMRI Rubyインタープリタは複数のCPUコアを利用できないことです。各プロセスはCPUコアを利用できるため、複数のマルチスレッドプロセスを使用することでこれを回避できます。 JRubyとRubiniusにはGILがないため、1つのプロセスで複数のコアを完全に活用できます。
- ハイブリッドマルチスレッドマルチプロセス主にPhusion Passenger Enterprise 4以降で実装されています。シングルスレッドのマルチプロセス、純粋なマルチスレッド、あるいはそれぞれが複数のスレッドを持つ複数のプロセスを簡単に切り替えることができます。このモデルは両方の長所を提供します。
- Evented。このモデルは、前述のモデルとはまったく異なります。非常に高いI/O同時実行性を可能にするため、長時間のブロッキングI/Oワークロードに最適です。それを利用するには、アプリケーションとフレームワークからの明示的なサポートが必要です。しかしRailsやSinatraのようなすべての主要なフレームワークはイベントコードをサポートしていません。これが、実際にはシンプロセスが依然として一度に複数の要求を処理できず、シングルスレッドのマルチプロセスモデルと実質的に同じ動作をする理由です。 Crampのように、平等化されたI/Oを利用できる特殊なフレームワークがあります。
ワークロードを考慮してプロセスとスレッドの数を最適に調整することに関する記事がPhusionブログに最近投稿されました。 Tuning Phusion Passengerの並行処理設定 を参照してください。
カピストラーノ
カピストラーノは全く違うものです。これまでのすべてのセクションで、「デプロイ」とはアプリケーションサーバーでRubyアプリケーションを起動して訪問者がアクセスできるようにすることを指しますが、その前に通常は次のような準備作業を行う必要があります。
- Rubyアプリのコードとファイルをサーバーマシンにアップロードします。
- アプリが依存するライブラリをインストールする。
- データベースの設定または移行.
- Sidekiq/Resqueワーカーなど、アプリが依存する可能性のあるデーモンの起動と停止。
- アプリケーションを設定するときに必要なその他の作業.
カピストラーノの文脈では、「展開」とは、この準備作業をすべて行うことを指します。 Capistranoはアプリケーションサーバーではありません。代わりに、それはすべてのその準備作業を自動化するためのツールです。 Capistranoに、自分のサーバーの場所と、新しいバージョンのアプリをデプロイするたびに実行する必要があるコマンドを指示します。Capistranoは、Railsアプリをサーバーにアップロードし、指定したコマンドを実行します。
Capistranoは常にアプリケーションサーバーと組み合わせて使用されます。アプリケーションサーバーに代わるものではありません。逆に、アプリケーションサーバーはCapistranoに代わるものではなく、Capistranoと組み合わせて使用することができます。
もちろん、Capistranoを使う必要はありません。 RubyアプリをFTPでアップロードし、毎回同じ手順のコマンドを手動で実行したい場合は、それを実行できます。他の人々はそれにうんざりしていたので、彼らはCapistranoでそれらのステップを自動化します。