nginx + fastCGI + Django-클라이언트로 전송 된 응답에서 데이터 손상 가져 오기


10

FastCGI를 사용하여 nginx 뒤에 Django를 실행하고 있습니다. 클라이언트로 전송 된 일부 응답에서 응답 중간에 임의의 데이터 손상이 발생한다는 것을 발견했습니다 (중간에 몇 백 바이트 정도일 수 있음).

이 시점에서 나는 장고 서버를 독립형 (즉 runserver) 모드로 실행할 때이 문제가 발생하지 않기 때문에 nginx의 FastCGI 처리기 또는 Django의 FastCGI 처리기 (즉, 플랩의 버그) 중 하나 인 버그로 좁혔습니다 . FastCGI 모드에서만 발생합니다.

다른 흥미로운 트렌드 :

  • 더 큰 응답에서 발생하는 경향이 있습니다. 클라이언트가 처음 로그인하면 1MB 청크가 전송되어 서버 DB와 동기화됩니다. 첫 번째 동기화 후 응답은 훨씬 작습니다 (보통 한 번에 몇 KB). 손상은 항상 처음에 전송 된 1MB 청크에서 발생하는 것으로 보입니다.

  • 클라이언트가 LAN을 통해 서버에 연결된 경우 (즉, 지연 시간이 짧은 고 대역폭 연결) 더 자주 발생합니다. 이것은 nginx 또는 flup에 일종의 경쟁 조건이 증가하여 데이터 속도가 증가한다고 생각합니다.

지금은 응답 헤더에 추가 SHA1 다이제스트를 넣고 헤더가 본문 체크섬과 일치하지 않는 응답을 클라이언트가 거부하도록 하여이 문제를 해결해야했지만 이것은 끔찍한 해결책입니다.

다른 사람이 이와 같은 것을 경험했거나 여기에 결함이있는 플랩인지 또는 nginx인지 식별하는 방법에 대한 조언이 있습니까? 그래서 적절한 팀에 버그를 제기 할 수 있습니까?

도움을 주셔서 감사합니다.

참고 : 나는 또한 여기에 잠시 동안 lighttpd + FastCGI + Django에 비슷한 버그를 게시했습니다 : https : //.com -예상치 못한 일이지만 ... (절단 대 손상) 같은 것은 아니지만 일반적인 원인은 웹 서버가 아니라 flup / Django 인 것처럼 보이기 시작합니다.

편집 : 나는 또한 내 환경이 무엇인지 주목해야합니다.

  • Mac Mini의 OSX 10.6.6

  • 파이썬 2.6.1 (시스템)

  • 장고 1.3 (공식 타르볼에서)

  • flup 1.0.2 (플 루프 사이트의 Python egg에서)

  • nginx + ssl 1.0.0 (Macports에서)

편집 : Jerzyk의 의견에 대한 응답으로 응답을 구성하는 코드 경로는 다음과 같습니다 (간결성을 위해 편집 됨).

# 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

나는 그것을 기반으로 Content-Length가 잘못되었을 가능성이 없다고 생각하며 AFAIK는 Django HttpResponse 객체를 텍스트와 달리 명시 적으로 바이너리로 표시 할 수있는 방법이 없습니다. 또한 문제가 간헐적으로 발생하기 때문에 모든 요청에서 볼 수 있다고 설명하지는 않습니다.

@ionelmc 편집 : Django에서 Content-Length를 설정해야합니다-nginx는 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

초기 청크가 자주 변경되지 않거나 사용자 특정이 아닌 경우 디스크에 쓰고 nginx를 통해 직접 제공하는 것이 더 좋은 방법입니까?
sunn0

불행히도, 청크는 사용자마다 다르고 자주 변경되기 때문에 이러한 종류의 캐싱은이 응용 프로그램에 적합하지 않습니다. 또한이 데이터 손상을 일으키는 원인을 해결하는 것이 아니라 헤더에서 여분의 SHA1 다이제스트로 이미 수행하고있는 것이 아니라 실제로이 데이터 손상을 일으키는 원인을 찾고 싶습니다.
glenc

두 가지 가능한 이유를 생각할 수 있습니다. 잘못된 인코딩-HttpRespose를 텍스트 대 바이너리 또는 잘못된 헤더 (특히 콘텐츠 길이)
Jerzyk

1
@glenc이 응답의 내용 유형은 무엇입니까? 이진 인 경우-설정할 수 있습니까? (예 : mimetype = 'application / x-ms-excel'등)
Jerzyk

2
Transfer-Encoding이 청크 된 경우 컨텐츠 길이를 설정할 필요가 없습니다. rfc 2616은이를 명시 적으로 금지합니다. "이 두 길이가 다른 경우 (즉, 전송 인코딩 헤더 필드가있는 경우) Content-Length 헤더 필드를 보내면 안됩니다."
ionelmc

답변:


1

fastcgi 응답에 대해 어떤 종류의 nginx 캐싱 (바이 패스 / no_cache) 지시문이 있습니까?

nginx '1.0.3 변경 사항에서 그들은 응답 손상을 수정했습니다.

버그 픽스 : "proxy / fastcgi / scgi / uwsgi_cache_bypass"및 "proxy / fastcgi / scgi / uwsgi_no_cache"지시문 값이 다른 경우 캐시 된 응답이 손상 될 수 있습니다. 버그는 0.8.46에 나타났습니다.

출처 : http://nginx.org/en/CHANGES (1.0.3. 섹션)


0

출력에 하나 이상의 UTF-8 문자가 포함 된 경우에만 가끔 손상이 발생할 수 있습니다.

하나의 UTF-8 문자는 2-5 바이트를 포함 할 수 있으므로 내용 길이와 문자열 길이는 동일하지 않습니다.


흠 .... 사실이지만 데이터 청크 중간에 손상이 발생했기 때문에 원인이 아닌 것 같으며 결국 데이터가 누락 된 경우가 아니기 때문입니다.
glenc

0

이 경우 문제를 해결하는 한 가지 방법은 다음과 같습니다.

  • nginx와 django를 다른 하드웨어에서 실행하십시오 (트래픽을 쉽게 캡처 할 수 있도록)
  • 클라이언트에서-/-> nginx 및 nginx-/-> django 로의 트래픽 캡처 (즉, wireshark 사용)

클라이언트 측에서 오류를 감지하면 (sha1 기반) 네트워크 캡처로 이동하여 기록 된 (TCP) 스트림을 살펴보고 nginx에 의해 문제가 생성되는지 아니면 django에서 직접 발생하는지 확인하십시오. .


0

이 설정을 사용 하는 한 매우 비슷한 문제 가 발생했습니다. 당신과 마찬가지로 FastCGI, Nginx 및 macOS를 사용하고 큰 요청 중에 무작위로 손상이 발견되었습니다 (1.5MB 문서 요청의 약 2 %였습니다).

PHP-FPM (필자의 경우)과 Nginx 간의 FastCGI 연결을 위해 TCP를 통해 Unix 소켓으로 전환하여 문제를 해결할 수있었습니다. 어떤 퍼즐 조각이 손상의 원인인지는 모르지만 내부 TCP 연결을 피하면 문제가 해결되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.