nginx upload client_max_body_size sorunu


117

Nginx / ruby-on-rails çalıştırıyorum ve dosyaları yüklemek için basit bir çok bölümlü formum var. Yüklenmesini istediğim maksimum dosya boyutunu kısıtlamaya karar verene kadar her şey yolunda gidiyor. Bunu yapmak için, ben nginx set client_max_body_sizeiçin 1m (1MB) ve tepki zaman bu kural sonları bir HTTP 413 (Talep Çok Büyük) durumunu bekliyoruz.

Sorun şu ki, HTTP 413 hata sayfasını görüntülemek yerine 1,2 MB'lik bir dosya yüklediğimde, tarayıcının biraz takılması ve ardından "Sayfa yüklenirken bağlantı sıfırlandı" mesajı ile ölmesi.

Nginx'in sunduğu hemen hemen her seçeneği denedim, hiçbir şey işe yaramıyor. Bunun hakkında herhangi bir fikri olan var mı?

İşte benim nginx.conf'um:

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

Teşekkürler.


**Edit**

Ortam / UA: Windows XP / Firefox 3.6.13

Yanıtlar:


128

İstemci, client_max_body_sizebir 413 yanıtı göndererek ve bağlantıyı kapatarak, istemciden daha büyük bir gövde göndereceğini bildirdiğinde nginx "hızlı başarısız" olur .

Çoğu istemci, istek gövdesi gönderilinceye kadar yanıtları okumaz. Nginx bağlantıyı kapattığından, istemci kapalı sokete veri göndererek bir TCP RST'ye neden olur.

HTTP istemciniz destekliyorsa, bunun üstesinden gelmenin en iyi yolu bir Expect: 100-Continuebaşlık göndermektir . Nginx doğru 1.2.7 itibariyle bu destekler ve bir ile cevap verecektir 413 Request Entity Too Largeziyade tepki 100 Continueise Content-Lengthmaksimum vücut boyutu aşıyor.


1
Oh, bu yanıt istemci gönderdiğini varsayar işaret olmalıdır Content-Lengthziyade yapıyor Transfer-Encoding: chunked.
Joe Shaw

2
Nginx yazarı, posta listesinde bunu düzeltmek için bir yama yayınladı: nginx.2469901.n2.nabble.com/… Ancak 1.2.x kararlı dalına eklenip eklenmeyeceğine dair bir kelime yok.
Joe Shaw

Teşekkürler, bu aslında pek çok şeyi açıklıyor. Kesinlikle Expectbüyük talepler için gitmenin yolu gibi görünüyor .
krukid

Cevabım, daha önce bahsettiğim yamanın taahhüt edildiğini ve 1.2.7 sürümüne dahil edildiğini belirtmek için güncellendi.
Joe Shaw

: Sadece (I harcanan gibi) güzel bir sözdizimi aramak zaman kazanmak için request.setHeader(HttpHeaders.EXPECT, CONTINUE);birlikte import org.apache.http.HttpHeaders;veimport static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CONTINUE;
Erez Cohen

48

Yüklemeniz en sonunda mı ölüyor? % 99 çökmeden önce mi? İstemci gövdesi ve tamponlar anahtardır çünkü nginx'in gelen verileri tamponlaması gerekir. Gövde yapılandırmaları (istek gövdesinin verileri), nginx'in çok parçalı form istemcilerinden gelen ikili verilerin toplu veri akışını uygulamanızın mantığına nasıl işlediğini belirtir.

Bu cleanayar, nginx'e gelen arabelleği bir dosyada saklamasını ve ardından bu dosyayı daha sonra silerek diskten temizlemesini söyleyerek belleği ve tüketim sınırlarını boşaltır.

Set body_in_file_onlyiçin cleanve tampona ayarlayın client_max_body_size. Orijinal sorunun yapılandırması zaten dosya gönderme açıktı, zaman aşımlarını da artırdı. Bunu düzeltmek için aşağıdaki ayarları yerel yapılandırma, sunucu ve http bağlamlarınıza uygun olarak kullanıyorum.

client_body_in_file_only clean;
client_body_buffer_size 32K;

client_max_body_size 300M;

sendfile on;
send_timeout 300s;

Bu, nginx'in uygun bir HTTP 413 döndürmesiyle sonuçlansa bile, UA yine de istek gövdesinin tamamını göndermeye devam edecek, değil mi? Bu durumda, @ joe-shaw'ın önerdiği yaklaşımı denemeye değer olduğunu düşünüyorum.
krukid

@krukid, NGINX'in "hızlı başarısız" olmasından önce yüklemenin% 99'unu tamamladığımıza bakıldığında, sana katılıyorum. Bu durumda, istek nesnesini çevreleyen tüm işaretler pozitiftir, yani teşhis, dahili sunucu uygulaması mantığının iyi olduğudur - Nginx'in arkasında ne olursa olsun. Bu nedenle, istek büyük olasılıkla iyi oluşturulmuş olsa da, ihtiyacımız NGINX'in yanıtta neden tıkandığını düşünmektir. client_max_body_size, baktığımız ilk yapılandırma seçeneği olmalı, ardından arabellekleri göz önünde bulundurmalı, çünkü yeterince büyük bir yükleme ile doğru çözüm, sunucumuzun ne kadar bellek kullanabileceğine de bağlıdır.
Bent Cardan

@Bent Cardan. Bu yaklaşım daha iyi görünüyordu ve denedim. Ama yine de 4mb'lik bir dosya için yaklaşık 20 saniye sonra 413 hatası alıyorum. Hızlarım 20 saniyede 4 MB'yi yönetemiyor, bu yüzden veri oldukça uzun bir süre aktıktan sonra oluyor. Düşünceler?
Jerome

_Client_max_body_size 300M nginx.conf dosyasındaki değişiklikleri ekledim; dosya gönderme; gönderme_zaman aşımı 300s; _ Benim için mükemmel çalışıyor Teşekkürler
Ramesh Chand

Çözüm benim için çalışıyor openshift php7 nginx.
marlo

7

Gönderen belgeler :

Tarayıcıların bu hatayı nasıl doğru bir şekilde göstereceğini bilmediğini unutmamak gerekir.

Olanların bu olduğundan şüpheleniyorum, HTTP'yi Firebug veya Live HTTP Headers (her iki Firefox uzantısı) gibi araçları kullanarak ileri geri incelerseniz gerçekte neler olup bittiğini görebilirsiniz.


1
Buna burada da rastladım: forum.nginx.org/read.php?2,2620 nginx yazarının insanların lingering_time / lingering_timeout'u değiştirmeyi deneyebileceğini söylediği yerde - her ikisinin de benim durumumda hiçbir etkisi olmadı. Ayrıca, 1MB'lık bir limiti olan 1.2MB'lık dosyayı kolayca sabit bir 5Mbps bağlantıya sahip olarak yüklerken nasıl kalıcı bir zaman aşımı sorunu olabileceğini anlamıyorum. Yanıtı kokladım ve 413 sayfasını "Connection: close" başlığıyla gönderiyor, ancak bağlantı kapanmıyor.
krukid

Sanırım, mükemmel şekilde geçerli bir 413 HTTP durumu olmasına rağmen tarayıcılarda çalışmadığına inanmakta zorlanıyorum. İnsanların o sayfadan kurtulamadığı pek çok yeri Google'da araştırdım ve onu hiç görmedim bile.
krukid

Yolcuyu devre dışı bırakırsanız, bağlantıyı kapatır mı?
Mark Rose

Yolcu olan ve olmayan yanıtları karşılaştırdım. Her şey normal bir şekilde çalıştığında ve 1MB sınırlamamdan birkaç kat daha büyük (~ 14MB) bir dosya yüklediğimde, 413 yanıtı birçok kez alıyorum (çünkü istemci yığın göndermeye devam ediyor) ve son "Bağlantı sıfırlama" bir zaman aşımı gibi görünüyor. Yolcu olmadan bir 413 anında yanıt alıyorum ve tüm ilerleme duruyor, ancak yine de "Bağlantı sıfırlama" sayfasını görüyorum, statik 413.html'mi veya "Varlık Çok Büyük" anlamına gelen herhangi bir şeyi
görmüyorum
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.