Używam Django za nginx za pomocą FastCGI. Odkryłem, że w niektórych odpowiedziach wysyłanych do klienta przypadkowe uszkodzenie danych występuje w środku odpowiedzi (może to być kilkaset bajtów w środku).
W tym momencie zawęziłem to do bycia błędem w module obsługi FastCGI nginx lub w module obsługi FastCGI Django (tj. Prawdopodobnie błąd we flupie), ponieważ problem ten nigdy nie występuje, gdy uruchamiam serwer Django w trybie autonomicznym (tj. runserver
). Zdarza się to tylko w trybie FastCGI.
Inne ciekawe trendy:
Zdarza się to przy większych odpowiedziach. Gdy klient loguje się po raz pierwszy, wysyłany jest pakiet 1 MB fragmentów w celu zsynchronizowania ich z bazą danych serwera. Po tej pierwszej synchronizacji odpowiedzi są znacznie mniejsze (zwykle kilka KB na raz). Korupcja zawsze zdarza się w przypadku tych 1 MB fragmentów wysłanych na początku.
Zdarza się to częściej, gdy klient jest podłączony do serwera za pośrednictwem sieci LAN (tj. Połączenie o niskim opóźnieniu i dużej przepustowości). To sprawia, że myślę, że w nginx lub flup występuje jakiś warunek wyścigowy, który jest pogarszany przez zwiększoną szybkość transmisji danych.
W tej chwili musiałem obejść ten problem, umieszczając dodatkowy skrót SHA1 w nagłówku odpowiedzi i każąc klientowi odrzucić odpowiedzi, w których nagłówek nie zgadza się z sumą kontrolną treści, ale jest to trochę okropne rozwiązanie.
Czy ktoś jeszcze doświadczył czegoś takiego lub ma jakieś wskazówki, jak ustalić, czy to wina Flupa, czy Nginxa, więc mogę zgłosić błąd do odpowiedniego zespołu?
Z góry dziękuję za wszelką pomoc.
Uwaga: Podobny błąd opublikowałem także w lighttpd + FastCGI + Django jakiś czas tutaj: /programming/3714489/lighttpd-fastcgi-django-truncated-response-sent-to-client-due-to - nieoczekiwany ... mimo że nie jest to to samo (obcinanie a uszkodzenie), zaczyna wyglądać, jakby zwykłym winowajcą był flup / Django, a nie serwer WWW.
Edycja: Powinienem też zauważyć, jakie jest moje środowisko:
OSX 10.6.6 na komputerze Mac Mini
Python 2.6.1 (system)
Django 1.3 (z oficjalnego tarball)
flup 1.0.2 (z jaja Python na stronie flup)
nginx + ssl 1.0.0 (z Macports)
EDYCJA: W odpowiedzi na komentarz Jerzyka wygląda ścieżka kodu, która składa odpowiedź (edytowana dla zwięzłości):
# 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
Nie sądzę, że jest możliwe, aby na tej podstawie długość treści była błędna, a AFAIK nie ma sposobu, aby oznaczyć obiekt Django HttpResponse jako jawnie binarny w przeciwieństwie do tekstu. Ponadto, ponieważ problem występuje tylko sporadycznie, nie sądzę, że wyjaśnia to inaczej, prawdopodobnie można go zobaczyć przy każdym żądaniu.
EDYCJA @ionelmc: Musisz ustawić Content-Length w Django - nginx nie ustawia tego dla ciebie, jak w poniższym przykładzie, kiedy wyraźnie wyłączyłem ustawienie Content-Length:
$ 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
źródło
Odpowiedzi:
Czy masz jakąś dyrektywę buforowania nginx (bypass / no_cache) aktywną dla odpowiedzi fastcgi?
W Changenotes 1.0.3 nginx naprawili uszkodzenie odpowiedzi:
Źródło: http://nginx.org/en/CHANGES (sekcja 1.0.3.)
źródło
Być może sporadyczne uszkodzenie występuje tylko wtedy, gdy wyjście zawiera co najmniej jeden znak UTF-8.
Długość treści i długość łańcucha nie są tym samym, ponieważ jeden znak UTF-8 może zawierać od 2 do 5 bajtów.
źródło
Jednym ze sposobów rozwiązania tego problemu jest:
Po wykryciu błędu po stronie klienta (na podstawie sha1), przejdź do przechwytywania sieci, spójrz na nagrany strumień (TCP) i spróbuj sprawdzić, czy problem jest generowany przez nginx, czy pochodzi (bezpośrednio) z django .
źródło
Miałem bardzo podobny problem, który nękał mnie tak długo, jak miałem tę konfigurację. Podobnie jak ty, używam FastCGI, Nginx i macOS, i znalazłem przypadkowe uszkodzenie w środku dużych żądań (było to około 2% żądań dokumentu 1,5 MB).
Byłem w stanie rozwiązać problem, przełączając się na gniazda Unix przez TCP dla połączenia FastCGI między PHP-FPM (w moim przypadku) a Nginx. Nie wiem, która część układanki jest odpowiedzialna za uszkodzenie, ale uniknięcie wewnętrznego połączenia TCP naprawiło to.
źródło