ssig33.com

XSendFile でそこそこ高速にファイルを配信しつつなんかやる

ファイルをそこそこ高速に配信しつつ、裏でなんか処理をしたいとか、認証をかけたいとか、そういう事情があることはそれなりにあります。

配信状況を確認したいという程度なら fluentd でログをひろってきてなにかすればいいでしょう。

とかなんとか難しい条件があると難しいという話になります。ここで本当に高速なアプリケーションを開発したい場合 nginx に拡張を書くというのが現実的な解となってくるでしょう。そういうことをするには本物の C++ プログラマーが必要ということになってきます。さらにリソースが潤沢ならば HTTP サーバーからなにから自分で書いてもよい。

ただ大体の場合そこまでギリギリの高速さが必要ではないでしょう。そこで XSendFile を使いましょう。速度と開発のしやすさのバランスがとれています。

これはアプリケーションがいい感じにヘッダを返して nginx やらがいい感じに設定されていれば、ファイルを nginx やらがいい感じに配信してくれるといういいやつです。

Sinatra を使う場合 sinatra-xsendfile という便利な Gem があります。

/home/apps/hoge というところで動いている Sinatra アプリケーションから、 /home/apps/hoge/data/fuga というファイルを前処理をしながら /fuga という URL などから配信したいとします。

アプリケーション側は以下のような感じになることでしょう

get '/fuga' do
  auth() # 認証とか
  before_process() # なんか難しい処理とか
  x_send_file "data/fuga"
end

これで nginx の設定をしていないと、 /home/apps/hoge/data/fuga へのアクセスがプログラミングされていないとか Sinatra が発狂するので nginx の server ディレクティブの中に

location /home/apps/hoge/data {
  alias /home/apps/hoge/data;
  internal;
}

とか書いておくといい感じに配信できます。

Ruby On Rails だと send_file 使いつつ X-Accel-Mapping ヘッダを返すとかすると同じような感じでいけます。やることは基本的にヘッダ返すだけなので他の言語やフレームワークでもなんかいい方法があるでしょう。 http://wiki.nginx.org/NginxXSendfile にだいたい必要なことが全部書かれています。

これで「複雑な前処理」のあらゆる部分を非同期化しキャッシュし血の滲むような努力をすれば画像にフィルタをかけつつ縮小拡大しつつ秒間 150 枚ぐらいをミドルレンジのサーバー 1 台で配信できるようになります。血の滲む努力と言っても全部 Ruby で済んでるので C++ 書くより多分マシ、以上です。

back to index of texts


Site Search

Update History of this content