Ruby on RailsおよびNginx:大きなファイルを効果的に配布する

この投稿では、Railsアプリケーションから大きなファイルを最も効率的にアップロードするために、Nginxを適切に設定する方法を説明します。 驚いたことに、私はロシア語でそのような情報を見つけませんでした。 X-Accel-Redirectをphpと組み合わせて使用​​することについての記事がありますが、母国語のレールについてはあまり説明しません...一般に、このギャップを埋めようとします。



挑戦する



したがって、初期データは次のとおりです。





解決策



英語圏の情報源への言及を避けたくはありませんが、公式のドキュメントを通過することはできません。 Nginxには、 X-Accel-Redirectのすばらしい部分があり、それによってタスクが解決されます。 次に、それを機能させる方法を示します。



Railsアプリケーションのconfig / environment / production.rbファイルで、次の行のコメントを解除する必要があります。

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
      
      





nginxの設定では、次を追加する必要があります。

 proxy_set_header X-Accel-Mapping /mnt/filestorage/=/private_files/; location /private_files/ { internal; alias /mnt/filestorage/; }
      
      





それだけです セットアップが完了しました。 ファイルのダウンロードの例で、これらすべてがどのように機能するかを見てみましょう。 この段階では、NginxとRailsアプリケーションはすでに構成され、動作していると考えています。



1.ブラウザがファイルを要求します

 # HTTP  GET /download/kino.avi HTTP/1.1
      
      





2. Nginxはこのリクエストを受信し、レールをアプリケーションに渡し、別のヘッダーを追加します。

 #  Nginx proxy_set_header X-Accel-Mapping /mnt/filestorage/=/private_files/;
      
      





 # HTTP  GET /download/kino.avi HTTP/1.1 X-Accel-Mapping: /mnt/filestorage/=/private_files/
      
      





3.アプリケーションのRailsコントローラーは、このユーザーにファイルを提供できるかどうかを確認し、send_fileを呼び出します。 この時点で、絶対パスを使用することが重要です。

 #  rails  ( app/controllers/downloads_controller.rb) send_file('/mnt/filestorage/kino.avi')
      
      





4. Rails(またはRack)がこのファイルの処理方法を決定します。 この段階の前半では、ファイルの内容が応答本文に含まれていました。 しかし、Railsアプリケーションの設定を変更すると、ファイルのコンテンツの代わりに、応答にX-Accel-Redirectヘッダーが含まれ、Nginxが処理します。 応答本文は空になります。 また、ファイルパスは、X-Accel-Mappingヘッダーからの情報に従って変更されます。

 #  Rails (config/environments/production.rb) config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
      
      





 # HTTP  HTTP/1.1 200 OK X-Accel-Redirect: /private_files/kino.avi Content-Type: application/octet-stream Content-length: ... Content-Disposition: attachment; filename="kino.avi"   
      
      





5. Nginxはこのヘッダーを処理し、適切な場所を見つけ、ファイルパスを変更してユーザーに提供します。

 #  Nginx location /private_files/ { internal; alias /mnt/filestorage/; }
      
      





 # HTTP  HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Length: ... Content-Disposition: attachment; filename="kino.avi" < /mnt/filestorage/kino.avi>
      
      





6.ユーザーのブラウザがファイルを受信します。



Passengerを使用する場合、Nginx構成では、 proxy_set_header



代わりにproxy_set_header



を使用する必要があります



All Articles