nginx mengunggah masalah client_max_body_size

117

Saya menjalankan nginx / ruby-on-rails dan saya memiliki formulir multi-bagian sederhana untuk mengunggah file. Semuanya berfungsi dengan baik sampai saya memutuskan untuk membatasi ukuran maksimum file yang ingin saya unggah. Untuk melakukan itu, saya mengatur nginx client_max_body_sizeke 1m (1MB) dan mengharapkan status HTTP 413 (Request Entity Too Large) sebagai tanggapan ketika aturan itu rusak.

Masalahnya adalah ketika saya mengunggah file 1,2 MB, alih-alih menampilkan halaman kesalahan HTTP 413, browser sedikit macet dan kemudian mati dengan pesan "Sambungan disetel ulang saat halaman sedang dimuat".

Saya sudah mencoba hampir semua opsi yang ada yang ditawarkan nginx, sepertinya tidak ada yang berhasil. Apakah ada yang punya ide tentang ini?

Inilah nginx.conf saya:

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;    
    }    
}

Terima kasih.


**Edit**

Lingkungan / UA: Windows XP / Firefox 3.6.13

krukid
sumber

Jawaban:

128

nginx "gagal dengan cepat" ketika klien memberitahunya bahwa itu akan mengirim tubuh yang lebih besar dari client_max_body_sizedengan mengirimkan respons 413 dan menutup koneksi.

Sebagian besar klien tidak membaca tanggapan sampai seluruh isi permintaan dikirim. Karena nginx menutup koneksi, klien mengirim data ke soket tertutup, menyebabkan TCP RST.

Jika klien HTTP Anda mendukungnya, cara terbaik untuk menanganinya adalah dengan mengirim Expect: 100-Continueheader. Nginx mendukung ini dengan benar mulai 1.2.7, dan akan membalas dengan 413 Request Entity Too Largerespons daripada 100 Continuejika Content-Lengthmelebihi ukuran tubuh maksimum.

Joe Shaw
sumber
1
Oh, saya harus menunjukkan bahwa jawaban ini mengasumsikan bahwa klien mengirim Content-Lengthdaripada melakukan Transfer-Encoding: chunked.
Joe Shaw
2
Penulis nginx memposting tambalan untuk memperbaikinya di milis: nginx.2469901.n2.nabble.com/… Tidak ada kabar apakah itu akan ditambahkan ke cabang stabil 1.2.x.
Joe Shaw
Terima kasih, itu menjelaskan banyak hal. Sepertinya Expectcara untuk pergi untuk permintaan besar.
krukid
Memperbarui jawaban saya untuk mencatat bahwa tambalan yang saya sebutkan sebelumnya telah dilakukan dan dimasukkan ke dalam rilis 1.2.7.
Joe Shaw
Hanya untuk menghemat waktu mencari sintaks yang bagus (seperti yang saya habiskan): request.setHeader(HttpHeaders.EXPECT, CONTINUE);dengan import org.apache.http.HttpHeaders;danimport static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CONTINUE;
Erez Cohen
48

Apakah unggahan Anda mati di akhir? 99% sebelum mogok? Tubuh klien dan buffer adalah kuncinya karena nginx harus menyangga data yang masuk. Konfigurasi body (data dari request body) menentukan bagaimana nginx menangani aliran massal data biner dari klien multi-part-form ke dalam logika aplikasi Anda.

The cleanPengaturan membebaskan memori dan konsumsi batas dengan menginstruksikan nginx untuk menyimpan penyangga yang masuk dalam file dan kemudian membersihkan file ini kemudian dari disk dengan menghapus itu.

Setel body_in_file_onlyke cleandan sesuaikan buffer untuk client_max_body_size. Konfigurasi pertanyaan asli sudah mengaktifkan sendfile, tambah waktu tunggu juga. Saya menggunakan pengaturan di bawah untuk memperbaikinya, sesuai dengan konteks konfigurasi, server, & http lokal Anda.

client_body_in_file_only clean;
client_body_buffer_size 32K;

client_max_body_size 300M;

sendfile on;
send_timeout 300s;
Bent Cardan
sumber
Meskipun hal ini mengakibatkan nginx mengembalikan HTTP 413 yang benar, UA masih akan mengirimkan keseluruhan isi permintaan, bukan? Dalam hal ini saya pikir ada baiknya mencoba pendekatan yang disarankan @ joe-shaw.
krukid
@krukid ketika kelihatannya kita mendapatkan 99% unggahan selesai sebelum NGINX "gagal dengan cepat," Saya setuju dengan Anda. Dalam hal ini, semua tanda positif di sekitar objek permintaan, yaitu diagnosisnya adalah logika aplikasi server internal baik-baik saja - apa pun yang berjalan di belakang Nginx. Jadi, meskipun kemungkinan permintaan telah dibuat dengan baik, kebutuhan kami adalah untuk mempertimbangkan mengapa NGINX tersedak tanggapan. client_max_body_size harus menjadi opsi konfigurasi pertama yang kita lihat, kemudian pertimbangkan buffernya, karena dengan unggahan yang cukup besar, solusi yang tepat tergantung pada seberapa banyak memori yang dapat ditangani server kita juga.
Bent Cardan
@Kartun_anak. Pendekatan ini tampaknya lebih baik dan saya mencobanya. Tapi saya masih mendapatkan kesalahan 413 setelah sekitar 20 detik untuk file 4mb. Peningkatan saya tidak dapat mengelola 4 MB dalam 20 detik sehingga ini terjadi setelah data mengalir cukup lama. Pikiran?
Jerome
Saya telah menambahkan perubahan pada file nginx.conf _client_max_body_size 300M; sendfile aktif; send_timeout 300s; _ Ini bekerja dengan sempurna untuk saya Terima kasih
Ramesh Chand
Solusi bekerja untuk saya openshift php7 nginx.
marlo
7

Dari dokumentasi :

Perlu diingat bahwa browser tidak tahu cara menampilkan kesalahan ini dengan benar.

Saya menduga inilah yang terjadi, jika Anda memeriksa HTTP ke sana kemari menggunakan alat seperti Firebug atau Live HTTP Headers (keduanya ekstensi Firefox), Anda akan dapat melihat apa yang sebenarnya terjadi.

ZoFreX
sumber
1
Saya telah menemukannya di sini juga: forum.nginx.org/read.php?2,2620 Di mana penulis nginx mengatakan orang dapat mencoba mengubah lingering_time / lingering_timeout - keduanya tidak berpengaruh pada kasus saya. Selain itu, saya hanya tidak melihat bagaimana mungkin ada masalah waktu tunggu yang terus-menerus ketika saya mengunggah file 1,2MB dengan batas 1MB dengan mudah memiliki koneksi 5Mbps yang stabil. Saya telah mengendus responsnya dan itu mengirim halaman 413 dengan header "Connection: close", tetapi koneksi tampaknya tidak menutup.
krukid
Saya rasa saya hanya kesulitan mempercayai bahwa meskipun ada status HTTP 413 yang benar-benar valid, itu tidak menyala di browser. Saya telah mencari di Google banyak tempat di mana orang tidak dapat menyingkirkan halaman itu, dan saya bahkan tidak pernah melihatnya.
krukid
Jika Anda menonaktifkan penumpang, apakah itu menutup koneksi?
Mark Rose
Nah, saya membandingkan tanggapan dengan dan tanpa penumpang. Ketika semuanya berjalan normal dan saya mengunggah file beberapa kali lebih besar (~ 14MB) dari batasan 1MB saya, saya mendapatkan respons 413 beberapa kali (karena klien terus mengirimkan potongan) dan "Reset koneksi" terakhir terlihat seperti batas waktu. Tanpa penumpang, saya mendapat respons instan 413 dan semua kemajuan berhenti, tetapi saya masih melihat halaman "Reset koneksi", bukan 413.html statis saya atau apa pun yang menyiratkan "Entitas Terlalu Besar"
krukid