nginxアップロードclient_max_body_sizeの問題


117

nginx / ruby​​-on-railsを実行していますが、ファイルをアップロードするためのシンプルなマルチパートフォームがあります。アップロードするファイルの最大サイズを制限するまで、すべてが正常に機能します。そのために、私はnginx client_max_body_size1m(1MB)に設定し、そのルールが破られたときの応答としてHTTP 413(リクエストエンティティが大きすぎます)ステータスを予期します。

問題は、HTTP 413エラーページを表示する代わりに1.2 MBのファイルをアップロードすると、ブラウザが少しハングし、「ページのロード中に接続がリセットされました」というメッセージが表示されて停止することです。

私はnginxが提供するオプションのほとんどすべてを試しましたが、何も機能しないようです。誰かこれについて何か考えがありますか?

ここに私のnginx.confがあります:

worker_processes  1;
timer_resolution  1000ms;
events {
    worker_connections  1024;
}

http {
    passenger_root /the_passenger_root;
    passenger_ruby /the_ruby;

    include       mime.types;
    default_type  application/octet-stream;

    sendfile           on;
    keepalive_timeout  65;

    server {
      listen 80;
      server_name www.x.com;
      client_max_body_size 1M;
      passenger_use_global_queue on;
      root /the_root;
      passenger_enabled on;

      error_page 404 /404.html;
      error_page 413 /413.html;    
    }    
}

ありがとう。


**Edit**

環境/ UA:Windows XP / Firefox 3.6.13

回答:


128

nginxは、クライアントがそれよりも大きなボディを送信することを通知すると、「速く失敗します」 client_max_body_size、413応答を送信して接続を閉じることにより。

ほとんどのクライアントは、要求本文全体が送信されるまで応答を読み取りません。nginxが接続を閉じるため、クライアントは閉じたソケットにデータを送信し、TCP RSTが発生します。

HTTPクライアントがサポートしている場合、これを処理する最良の方法は、Expect: 100-Continueヘッダーを送信することです。Nginxは1.2.7でこれを正しくサポートし、最大本体サイズを超えている場合では413 Request Entity Too Largeなく、応答で応答します。100 ContinueContent-Length


1
ああ、私はこの回答がクライアントが送信するのContent-Lengthではなく送信することを前提としていることを指摘しておきますTransfer-Encoding: chunked
Joe Shaw、

2
nginxの作者は、これを修正するためのパッチをメーリングリストに投稿しました:nginx.2469901.n2.nabble.com/…しかし 、1.2.xの安定版ブランチに追加されるかどうかはわかりません。
Joe Shaw

ありがとう、それは実際に多くを説明します。確かExpectに大規模なリクエストを処理する方法のように見えます。
krukid 2013年

以前に述べたパッチがコミットされ、1.2.7リリースに組み込まれたことを注記するように私の回答を更新しました。
Joe Shaw、

ただ、(私が過ごしたように)素敵な構文を探して時間を節約するために:request.setHeader(HttpHeaders.EXPECT, CONTINUE);import org.apache.http.HttpHeaders;import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CONTINUE;
エレズコーエン

48

アップロードは最後に終了しますか?クラッシュする前に99%?nginxは着信データをバッファリングする必要があるため、クライアント本体とバッファが重要です。本文の構成(リクエスト本文のデータ)は、nginxがマルチパートフォームクライアントからアプリのロジックへのバイナリデータのバルクフローを処理する方法を指定します。

このclean設定は、nginxに着信バッファーをファイルに格納し、後でこのファイルを削除してディスクから削除するように指示することにより、メモリと消費制限を解放します。

のバッファをに設定body_in_file_onlycleanて調整しますclient_max_body_size。元の質問の設定にはすでにsendfileがあり、タイムアウトも増やしています。以下の設定を使用して、ローカルの構成、サーバー、およびhttpコンテキスト全体で適切にこれを修正します。

client_body_in_file_only clean;
client_body_buffer_size 32K;

client_max_body_size 300M;

sendfile on;
send_timeout 300s;

これによりnginxが適切なHTTP 413を返す場合でも、UAはリクエスト本文全体を送信することになりませんか?その場合、@ joe-shawが提案するアプローチを試す価値があると思います。
krukid 2013

@krukidの場合、NGINXが「すぐに失敗する」前に99%のアップロードが完了したようです。この場合、リクエストオブジェクトを取り巻くすべての兆候は肯定的です。つまり、診断は、内部サーバーアプリケーションロジックに問題がないことを示します。Nginxの背後で実行されるものは何でも。したがって、リクエストが適切に形成されている可能性は高いですが、NGINXが応答を窒息させる理由を検討する必要があります。client_max_body_sizeは、最初に確認する構成オプションである必要があります。次に、バッファーを検討します。十分に大きいアップロードでは、正しいソリューションはサーバーが処理できるメモリの量にも依存するためです。
ベントカルダン

@ベントカルダン。このアプローチの方が良いようで、試してみました。しかし、4mbファイルの場合、約20秒後も413エラーが発生します。私のアップスピードは20秒で4 MBを管理できないため、データがかなり流れ続けた後に発生しています。考え?
ジェローム

nginx.confファイル_client_max_body_size 300Mに変更を追加しました。sendfile on; send_timeout 300s; _おかげで完璧に機能しましたありがとう
Ramesh Chand

ソリューションは私のために働きopenshift php7 nginxます。
marlo 2016

7

ドキュメントから:

ブラウザはこのエラーを正しく表示する方法を知らないことに注意する必要があります。

これが起こっているのではないかと思います。FirebugLive HTTPヘッダー(両方ともFirefoxの拡張機能)などのツールを使用してHTTPの往復を調べれば、実際に何が起こっているのかを確認できます。


1
私も、ここにその全体で来ている:forum.nginx.org/read.php?2,2620 nginxの作成者は、人々が変更lingering_time / lingering_timeoutを試みることができると言う-どちらも私の場合は効果がなかったです。さらに、1 MBの制限がある1.2 MBのファイルをアップロードしているときに、5 Mbpsの安定した接続で簡単にタイムアウトの問題が発生する可能性があることはわかりません。応答をスニッフィングしたところ、「Connection:close」ヘッダーを含む413ページが送信されましたが、接続が閉じられていないようです。
krukid

完全に有効な413 HTTPステータスがあったとしても、ブラウザでは起動しないと信じるのに苦労しているだけだと思います。私は人々がそのページを取り除くことができない多くの場所をグーグルで回しました、そして私はそれを見さえしませんでした。
krukid

乗客を無効にすると、接続が切断されますか?
Mark Rose

さて、私は乗客の有無で反応を比較しました。すべてが正常に実行され、1MBの制限よりも数倍大きいファイル(〜14MB)をアップロードすると、413応答が複数回返され(クライアントがチャンクを送信し続けるため)、最後の「接続リセット」はタイムアウトのように見えます。乗客がなければ私は1つの413インスタント応答を取得し、すべての進歩は停止しますが、私はまだ「大エンティティあまりにも」意味「接続のリセット」ページではなく、私の静的413.htmlか何かを参照してください
krukid
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.