最近、
Sinatra::Helpers.send_file
を介して大きなファイルを提供しようとすると、すべてのRAMが消費されるという興味深い問題に遭遇しました(一般的なファイルサイズは14Gbです)。
この調査では、
Sinatra自体がファイルを512バイト単位で読み取り、提供しますが、シンWebサーバー(およびWEBrick)は独自のレベルでRAMに出力をバッファリングするため、このような悲しい結果につながります。
この問題を解決するには、
Rainbows Webサーバー(ユニコーンコードに基づくWebサーバーですが、遅いクライアントやサービスに対してプロキシなしで動作するように設計されています)に切り替えるだけで十分です。 ただし、大きなファイルを送信する場合、プロセスは1つのコアでCPUの約30%を消費しました。
Rainbowsでは、たとえばsendfile gemを使用して、
ファイルのアップロードを
最適化できます。sendfilegemは、オペレーティングシステムに適切なAPIを提供します。 ただし、このためには、ファイルのアップロードがRack :: File APIを経由する必要があります。
現在のSinatraマスターブランチでは、send_fileメソッドはRack :: File APIを使用して書き換えられたため、対応する機能をSinatra gemの既存のバージョンに簡単にバックポートできます。
if Sinatra::VERSION < '1.3.0' && Rack.release >= '1.3'
虹の構成ファイルは次のようになります。
gemラックバージョン1.3以降がシステムにインストールされ、sendfile gemがインストールされている場合、効果的なファイルアップロード手法を使用します。 ところで、ruby 1.9を使用する場合、sendfile gemはほとんど必要ありません。
PS:サービスがプロキシサーバーの背後にある場合、プロキシサーバーによって提供される機能、たとえば
X-Accel-Redirect(nginx)またはX-Sendfile(Lighttpd、Apache)APIを使用する方が最適です。