nginx + fastCGI + Django - istemciye gönderilen yanıtlarda veri bozulması alma


10

FastCGI kullanarak Django nginx arkasında çalıştırıyorum. İstemciye gönderilen yanıtların bazılarında, yanıtların ortasında rasgele veri bozulması oluştuğunu keşfettim (ortada birkaç yüz bayt olabilir).

Bu noktada ya nginx FastCGI işleyicisi veya Django FastCGI işleyicisi (yani muhtemelen flup bir hata) bir hata olarak daralttım, çünkü Django sunucusunu tek başına (ie runserver) modunda çalıştırdığınızda bu sorun asla oluşmaz . Sadece FastCGI modunda olur.

Diğer ilginç eğilimler:

  • Daha büyük yanıtlarda ortaya çıkma eğilimindedir. Bir istemci ilk kez oturum açtığında, bunları sunucu DB'siyle eşitlemek için 1 MB'lık bir grup gönderilir. Bu ilk senkronizasyondan sonra yanıtlar çok daha küçüktür (genellikle bir seferde birkaç KB). Yolsuzluk her zaman başlangıçta gönderilen 1 MB'lık parçalarda meydana gelir.

  • İstemci sunucuya LAN üzerinden bağlandığında daha sık olur (düşük gecikme süresi, yüksek bant genişliği bağlantısı). Bu, nginx veya flup'ta artan veri hızıyla şiddetlenen bir çeşit yarış durumu olduğunu düşündürüyor.

Şu anda, yanıt başlığına fazladan bir SHA1 özeti ekleyerek ve istemcinin başlığın vücut sağlama toplamıyla eşleşmediği yanıtları reddetmesini sağlayarak bu sorunu çözmek zorunda kaldım, ancak bu korkunç bir çözüm.

Herkes böyle bir şey yaşadı mı, ya da uygun bir takım ile bir hata dosyalamak böylece burada hatalı flup ya da nginx olup olmadığını belirlemek için herhangi bir işaret var mı?

Herhangi bir yardım için şimdiden teşekkürler.

Not: Ben de bir süre önce lighttpd + FastCGI + Django'da benzer bir hata gönderdim: /programming/3714489/lighttpd-fastcgi-django-truncated-response-sent-to-client-due-to -beklenmedik ... bu aynı şey olmasa da (yolsuzluk vs yolsuzluk), ortak suçlu web sunucusu yerine flup / Django gibi görünmeye başlıyor ..

Düzenleme: Ayrıca ortamımın ne olduğunu da not etmeliyim:

  • Mac Mini'de OSX 10.6.6

  • Python 2.6.1 (Sistem)

  • Django 1.3 (resmi tarball'dan)

  • flup 1.0.2 (flup sitesinde Python yumurtasından)

  • nginx + ssl 1.0.0 (Macports'tan)

DÜZENLEME: Jerzyk yorumuna yanıt olarak, yanıtı birleştiren kod yolu şöyle görünür (özlü olma için düzenlenmiştir):

# This returns an objc NSData object, which is an array.array 
# when pushed through the PyObjC bridge
ret = handler( request ) 

response = HttpResponse( ret )
response[ "Content-Length" ] = len( ret )
return response

Buna göre İçerik Uzunluğu'nun yanlış olduğunu düşünmüyorum ve AFAIK, bir Django HttpResponse nesnesini metnin aksine açıkça ikili olarak işaretlemenin bir yolu yok. Ayrıca, sorun sadece aralıklı olarak gerçekleştiği için, bunu her türlü talepte göreceğinizi düşünüyoruz.

@İonelmc DÜZENLEME: Django'da İçerik Uzunluğu'nu ayarlamanız gerekir - İçerik Uzunluğu ayarını açıkça devre dışı bıraktıktan sonra aşağıdaki örneğe göre nginx bunu sizin için ayarlamaz:

$ curl -i http://localhost/io/ping
HTTP/1.1 200 OK
Server: nginx/1.0.0
Date: Thu, 23 Jun 2011 13:37:14 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive

AKSJDHAKLSJDHKLJAHSD

İlk parçalar sık ​​sık değişmiyorsa veya kullanıcıya özgü değilse, diske yazmak ve doğrudan nginx aracılığıyla hizmet vermek daha iyi bir yoldur?
sunn0

Ne yazık ki, parçalar hem kullanıcıya özgüdür hem de sık sık değişmektedir, bu nedenle bu tür bir önbellekleme bu uygulama için uygun olmayacaktır. Ayrıca, bu veri bozulmasına neyin neden olduğunu bulmak için sadece bunun üzerinde çalışmak yerine (bu zaten başlıkta ekstra SHA1 özeti ile yapıyorum) bulmak için istekli.
glenc

İki olası nedeni düşünebilirim: yanlış kodlama - HttpRespose olarak ikili veya yanlış üstbilgilere karşı metin (özellikle içerik uzunluğu)
Jerzyk

1
@glenc bu yanıtın içerik türü nedir? Bu ikili ise - ayarlamayı deneyebilir misiniz? (örneğin, mimetype = 'application / x-ms-excel' or else)
Jerzyk

2
Transfer Kodlaması yığınlanmışsa içerik uzunluğunu ayarlamanız gerekmez. rfc 2616 bunu açıkça yasaklar: "Bu iki uzunluk farklıysa (yani, Aktarım Kodlaması başlık alanı varsa) İçerik Uzunluğu başlık alanı GÖNDERİLMEMELİDİR."
ionelmc

Yanıtlar:


1

Fastcgi yanıtları için etkin nginx önbellekleme (bypass / no_cache) yönergesi var mı?

Nginx '1.0.3 Changenotes uygulamasında bir yanıt bozulması düzeltildi:

Bugfix: "proxy / fastcgi / scgi / uwsgi_cache_bypass" ve "proxy / fastcgi / scgi / uwsgi_no_cache" yönergesi değerleri farklıysa önbelleğe alınmış bir yanıt bozulabilir; hata 0.8.46'da ortaya çıkmıştı.

Kaynak: http://nginx.org/en/CHANGES (1.0.3. Bölüm)


0

Belki de ara sıra yolsuzluk yalnızca çıktı en az bir UTF-8 karakteri içeriyorsa meydana gelir.

Bir UTF-8 karakteri 2 ila 5 bayt içerebileceğinden, içerik uzunluğu ve dize uzunluğu aynı şey değildir.


Hmmmm .. Bu doğru olsa da, bunun nedeni muhtemel görünmüyor çünkü veri yığınlarının ortasında bozulma meydana geliyordu ve sonunda veri eksik olmuyor.
glenc

0

Bu durumda biraz daha sorun gidermenin bir yolu:

  • nginx ve django'nun farklı donanımlarda çalışmasını sağlayın (böylece trafiği kolayca yakalayabilirsiniz)
  • istemciden - / -> nginx ve nginx - / -> django'ya giden trafiği yakalayın (yani wireshark kullanın)

İstemci tarafında (sha1'e dayalı olarak) bir hata algıladıktan sonra, ağ yakalamaya gidin, kaydedilen (TCP) akışına bakın ve sorunun nginx tarafından üretilip üretilmediğini veya django'dan (doğrudan) gelip gelmediğini bulmaya çalışın .


0

Ben çok benzer bir sorunu olduğu sürece ben bu kurulumu yaşadım beni saran edildi. Senin gibi FastCGI, Nginx ve macOS kullanıyorum ve büyük isteklerin ortasında rastgele bir yolsuzluk buldum (1.5 MB'lik bir belgenin isteklerinin yaklaşık% 2'si).

PHP-FPM (benim durumumda) ve Nginx arasındaki FastCGI bağlantısı için TCP üzerinden Unix soketlerine geçerek sorunumu çözebildim. Bulmacanın hangi parçasının bozulmadan sorumlu olduğunu bilmiyorum, ancak dahili TCP bağlantısından kaçınmak sorunu çözdü.

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.