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を使用する必要があります

Source: https://habr.com/ru/post/J172531/


All Articles