Develop with pleasure!

福岡でCloudとかBlockchainとか。

Passenger vs Unicorn

EnginYardのブログにポストされてた記事を意訳してみた。

Passenger vs. Unicorn | Engine Yard Blog | Engine Yard Developer Blog

UnicornとPassengerは根本的な動作仕様が異なってるけど、

  • ワーカーを生成するマスタープロセスの存在
  • マスタープロセスからワーカーがフォークされる
  • Rackベースのアプリケーションに加えて旧バージョンのRailsもサポートしている

といった類似点もある。

以下に2つのアプリケーションサーバの利点と問題点についてまとめてみる。

Passenger

PassengerはApacheやNginxのモジュールで、mod_phpとmod_ruby上でモデル化されてて、Engine Yardでは、パフォーマンスや設定ファイルのシンプルさメモリ使用量の低さからNginxを使ってる。NginxでPassengerを使用する場合、Passengerはリクエストが発生したタイミングで(ワーカーを生成するための)マスタープロセスを生成する。マスタープロセス自体は比較的高速に生成されるけど、Railsのコードがロードされるまで少し時間がかかる。起動時間は5秒弱くらいだが、アプリケーションのロード等で30秒くらいはかかる。

Nginxの設定ファイルの定義値によってPassengerのワーカープロセスの数は制限されていて、リクエストが来てる間はワーカープロセスは生き続ける。各アプリケーションはリクエストを捌くのに必要な数だけしかワーカープロセスを保持しない。リクエストを捌くのに多数のワーカーが必要ない場合は、設定ファイルに定義されてる最小数までワーカープロセスは削減される。リクエストを捌くための必要最低限のメモリしか使わないので、1アプリが1ワーカーしか使用しないのであれば、そのワーカーに必要なメモリを除いて、残りのメモリは他のアプリケーションで有効利用される。

1つのPassenger上でいろんなアプリケーションを走らせることができるのは便利だけど、Passengerにはいくつか欠点もある。(監視するのは難しいんだけど)1つのワーカープロセスに問題が発生し死んだ場合、誰かがそれをクリアするまでメモリのスタックに残ってしまう。Engine Yardではサポートエンジニアかpassenger_monitorというcronのジョブがクリアするようにしてる。一部のアプリケーションではこの問題を抱えているが、発生条件は負荷状況とリクエスのボリュームに依存する模様。また、Passengerを再起動すると時々古いアプリケーションプロセスがマスタープロセスのkillシグナルに応答しない。現在クラウド上では自動的にそれらをkillする仕組みは存在せず、サーバが高負荷状態にある場合は特に問題となる。

これらの問題はさておき、それ以外にも3つの問題がある。

  • ウォームアップタイム
  • シームレスなデプロイに不向き
  • Webサーバにコンパイルして組み込まれてるのでUnicornのようなアプリケーションサーバと違って独自に詳細なプロキシの設定ができない。

Unicorn

一方、Unicornは多少動作が異なる。Unicornは他のスタックとは独立して動作する。マスタープロセスが以下の責務を持つ。

  1. メモリ内に実行中のコードのコピーを保持する。
  2. ワーカーがリクエストを処理するまでにかかる時間を監視する。
  3. リクエストを処理するのに長時間かかっているワーカーをkillして、高速に(ミリ秒のオーダーで)新しいワーカーをフォークする。
  4. 新しいコードによるGracefulな再起動が可能。この動作の流れは、コードが更新されるとUSR2シグナルを送る→新しいマスタープロセスとワーカープロセスを起動する→古いいワーカープロセスは今かかえているリクエストの処理が終わったら終了する。この方法はゼロダウンタイムデプロイを可能にする。

Unicornはメモリ内に生きているワーカープロセスのセット数を保持している。(Engin Yard Cloud上ではこの数はインスタンスサイズに基づいて設定されてる)全てのリクエストは、ドメインソケットを介してカーネルメソッドにより受け付けられる。これはワーカープロセスのロードバランシングがカーネルによって管理されることを意味し、非常に効率的である。これは比較的静的な設定であるため、CPUやメモリの使用量の監視にMonitを使用することが可能。

メモリの消費についてはUnicornにとっては不利になる。アプリケーションコードによって必要とされるものは全てメモリ上に展開され、マスタープロセスのオーバーヘッドになる。ただクラスタ環境では、そう悪いことでもなく、1台のサーバで動作させるのアプリケーションの数を効果的に制限できる。

参考文献:

http://unicorn.bogomips.org/
http://www.modrails.com/documentation/Users%20guide%20Nginx.html
http://tomayko.com/writings/unicorn-is-unix


意訳終了ー。
Passengerの死亡したワーカープロセスのメモリが残ったままになるとか面倒なので、Unicornクラスタ構成がよさげかなーと思ったけど、The right way to deal with frozen processes on Unix – Phusion Corporate BlogPhusion Corporate Blogの記事読むとPassenger 4で改善されるのか?