ApacheとPhusion PassengerでWebアプリケーションをデプロイしている際に、たまにシステムが不安定になることがありました。調査したところ、原因はレスポンスの取得が遅いクライアントであるということが分かりました。この問題を発見し、原因を特定し、Phusion Passengerを修正するまでについて、紹介します。
発見の経緯
るりまサーチではApacheとPhusion Passengerを使っているのですが、たまに動作が不安定になることがありました。その不安定の原因を調査することにしました。
原因の特定
調査した結果、遅いクライアントがるりまサーチに接続するのが不安定になるトリガーになっていることが分かりました。
以下に、詳しく説明します。
Phusion Passengerは、遅いクライアントが接続していると、他のリクエストの処理を行いません。その間に、他のクライアントからのリクエストが処理待ちとして大量に溜まります。そして遅いクライアントがレスポンスを受け取り終わると、Phusion Passengerは、一斉に溜まった処理待ちのリクエストを処理し始めるため、システムのリソースを急激に消費します。そして、システムが不安定になります。
解決の方法
この問題の原因を解決するためには、遅いクライアントのリクエストを処理している際にも、他のリクエストの処理ができればいいということになります。
遅いクライアントの時の状況を詳しく説明します。遅いクライアントがレスポンスを受け取るのを待っている間は、サーバー側ではレスポンスの作成の処理は既に完了しているということになります。それにも関わらず他のリクエストの処理を行わないのです。つまり、その間、サーバーは実質的には何も処理を行っていません!
この時間は、無駄な時間と言えます。
なので、この無駄な時間をなくすようにする必要があります。具体的には、Webアプリケーションからの作成されたレスポンスを一旦Phusion Passengerがバッファに保存し、次のリクエストの処理に移ります。遅いクライアントには、そこのバッファから、ゆっくりレスポンスを返せばいいのです。
実は、このような挙動はNginxとPhusion Passengerの構成でデプロイされた場合には実現されています。ですが、ApacheとPhusion Passengerの構成の場合にはそうでは無いのです。
情報の収集
解決の方法が分かったので調べたところ、Phusion Passengerのバグトラッキングシステムにこの問題はすでに登録されていました。
さらにそこには、この問題の解決方法が記載されていました。コメント#3の情報によるとソースコードを書き換えればいいということが分かりました。ソースコードを書き換えることで、Nginxと同じように、Apacheでもレスポンスをバッファに保存する挙動に変更できます。
実際に、るりまサーチで検証したところ、問題は解決されました。遅いクライアントが接続してきた際にも、処理が止まらず、別のリクエストを処理するようになりました。
Phusion Passengerの修正
問題は解決されましたが、この問題を解決するためには、ソースコードを書き換えなければいけません。端的に言って、これは不便です。上のバグレポート内に書いてあるように設定ファイルからレスポンスをバッファに保存するかどうかを切り替えられると便利です。
なので、設定できるようにPhusion Passengerを修正したパッチを作成しました。そしてそのパッチをPhusion Passengerに取り込んでもらうように依頼をしました。
(追記: Fri Nov 25 03:05:28 2011 JSTにPhusion Passengerに無事に取り込んでもらえました。使えるようになるのは、まだリリースされていませんが次のリリースバージョンである、3.0.10からの予定です)
(追記: November 28th, 2011にこの修正が取り込まれたPhusion Passengerの3.0.11がリリースされました(3.0.10はバグがあったためにスキップされました)。
この修正によって、レスポンスをバッファに保存するかどうかを次のように設定することができるようになります。
<VirtualHost *:80>
ServerName www.yourhost.com
DocumentRoot /somewhere/public
PassengerBufferResponse on
# PassengerBufferResponse off # レスポンスのバッファへの保存をしたくない場合。
<Directory /somewhere/public>
AllowOverride all
Options -MultiViews
</Directory>
</VirtualHost>
レスポンスをバッファに保存する副作用
遅いクライアント問題はレスポンスをバッファに保存することで解決できます。半面、レスポンスをバッファに保存すると、次の副作用が発生するので注意が必要です。
- レスポンスをストリーミングで返せない。
- レスポンスが非常に大きいとメモリを逼迫する。
どちらも、Phusion Passengerがレスポンスをメモリ上のバッファに一旦保存してからクライアントに返すようになるためです。
まとめ
ApacheとPhusion PassengerでデプロイされたWebアプリケーションが不安定になるという問題を調査し、Phusion Passengerを修正しました。
同じような問題に遭遇している場合には、ぜひ試してみてください。