104, '피어 소켓에 의한 연결 재설정'소켓 오류 또는 언제 소켓을 닫을 때 FIN이 아닌 RST가 발생합니까?

StackOverflow https://stackoverflow.com/questions/383738

문제

우리는 Python 웹 서비스와 클라이언트 웹 사이트를 병렬로 개발하고 있습니다. 클라이언트에서 서비스로 HTTP 요청을 할 때 한 호출은 Socket.py에서 소켓을 일관되게 올립니다.

(104, 'Connection reset by peer')

Wireshark와 함께들을 때 "좋은"및 "나쁜"응답은 매우 유사하게 보입니다.

  • OAUTH 헤더의 크기로 인해 요청이 두 패킷으로 분리됩니다. 서비스는 ACK로 둘 다에 응답합니다
  • 이 서비스는 응답, 헤더 당 하나의 패킷을 보냅니다 (HTTP/1.0 200 OK, 날짜 헤더 등). 클라이언트는 ACK로 각각에 응답합니다.
  • (양호한 요청) 서버는 FIN, ACK를 보냅니다. 클라이언트는 지느러미 ACK로 응답합니다. 서버가 ACK에 응답합니다.
  • (잘못된 요청) 서버는 RST, ACK를 보냅니다. 클라이언트는 TCP 응답을 보내지 않고 Socket.error가 클라이언트 측에서 올라갑니다.

웹 서비스와 클라이언트는 모두 GLIBC-2.6.1을 실행하는 Gentoo Linux X86-64 상자에서 실행 중입니다. 우리는 동일한 virtual_env 내에서 Python 2.5.2를 사용하고 있습니다.

클라이언트는 요청을하기 위해 httplib2 0.4.0을 호출하는 Django 1.0.2 앱입니다. OAUTH 서명 알고리즘과 함께 요청에 서명하고 있으며 OAUTH 토큰은 항상 빈 문자열로 설정되어 있습니다.

이 서비스는 Python의 WSGiref.simple_server를 사용하는 Werkzeug 0.3.1을 실행하고 있습니다. 문제없이 WSGIREF.Validator를 통해 WSGI 앱을 실행했습니다.

이는 디버깅하기 쉬운 것처럼 보이지만 서비스 측면에서 좋은 요청을 추적 할 때 소켓에서 잘못된 요청처럼 보입니다. Send 또는 Sendto (어떤 것을 기억할 수 없음) 메소드가 꺼져 있으면 FIN 또는 RST가 전송되고 클라이언트가 처리를 시작합니다.

"피어에 의한 연결 재설정"은 서비스에 비난을받는 것처럼 보이지만 httplib2도 신뢰하지 않습니다. 클라이언트가 잘못 될 수 있습니까?

** 추가 디버깅 - Linux의 서버처럼 보입니다 **

MacBook이 있으므로 하나는 서비스를 실행하려고했으며 다른 하나는 고객 웹 사이트에서 고객 웹 사이트를 사용했습니다. Linux 클라이언트는 버그없이 OS X 서버를 호출합니다 (FIN ACK). OS X 클라이언트는 버그로 Linux 서비스를 호출합니다 (RST ACK 및 A (54, 'Connection Reset By Peer'))). 따라서 Linux에서 실행되는 서비스 인 것 같습니다. x86_64입니까? 나쁜 glibc? wsgiref? 여전히 쳐다보다...

** 추가 테스트 -Wsgiref는 플라키처럼 보입니다 **

우리는 Apache 및 Mod_wsgi와 함께 프로덕션에 갔으며 연결 재설정이 사라졌습니다. 아래의 대답을 참조하십시오. 그러나 제 조언은 연결 재설정 및 재 시도를 기록하는 것입니다. 이렇게하면 서버가 개발 모드에서 정상화되고 생산에서 견고하게 실행됩니다.

도움이 되었습니까?

해결책

이 문제가있었습니다. 보다 Python "Connection Reset by Peer"문제.

Python Global Interpreter Lock을 기반으로 작은 타이밍 문제에 대한 (대부분)가 달려 있습니다.

당신은 이것을 (때로는) a로 수정할 수 있습니다 time.sleep(0.01) 전략적으로 배치되었습니다.

"어디에?" 물어. 나를 때린다. 아이디어는 클라이언트 요청과 주변에 더 나은 스레드 동시성을 제공하는 것입니다. 그냥 넣으십시오 ~ 전에 GIL이 재설정되고 Python 통역사가 보류중인 스레드를 지울 수 있도록 요청을합니다.

다른 팁

생산에 wsgiref를 사용하지 마십시오. Apache 및 Mod_wsgi 또는 다른 것을 사용하십시오.

WSGIREF (Werkzeug Test Server에서 사용하는 백엔드 및 Django Test Server와 같은 다른 사람들은 이러한 연결 재설정을 계속합니다. 우리의 해결책은 오류를 기록하고, 루프에서 통화를 다시 시도하고, 10 번의 실패 후 포기하는 것이 었습니다. httplib2는 두 번 시도하지만 몇 가지 더 필요했습니다. 그들은 또한 무리로 오는 것 같습니다. 1 초 수면을 추가하면 문제가 해결 될 수 있습니다.

Apache 및 Mod_wsgi를 통해 실행될 때 연결 재설정을 본 적이 없습니다. 나는 그들이 다르게 무엇을하는지 모르겠지만 (아마도 그들은 단지 그들을 가리는 것일 수도 있습니다), 그들은 나타나지 않습니다.

우리가 지역 개발자 커뮤니티에 도움을 요청했을 때, 누군가는 프로덕션 서버에서 사라지는 WSGIREF와 많은 연결이 재설정되어 있음을 확인했습니다. 거기에는 버그가 있지만 찾기가 어려울 것입니다.

나는 당신이 Python을 사용하고 있다는 것을 알고 있지만이 Java 기사가 유용하다는 것을 알았습니다.

http://java.sun.com/javase/6/docs/technotes/guides/ticles/connection_release.html

일반적으로 닫히지 않으면 RST를 얻을 수 있습니다. 머무르기 위해 (예 : 운송중인 데이터가 ACK'd가 될 때까지 근접한 대기).

아마도 소켓에서 소켓과 도착하는 ACKS의 비 링크 닫기 사이의 경주 상태를 제거하도록 소켓을 머무르기 만하면됩니다.

그러나 Nginx+UWSGI 백엔드에 게시하는 Python-Requests 클라이언트를 사용하여 매우 큰 파일을 업로드하는 것과 같은 문제가있었습니다.

결국 원인이 된 것은 백엔드가 클라이언트가 보내려고했던 것보다 최대 파일 크기에 상한을 가졌다는 것입니다.

이 한계는 실제로 Nginx에 의해 부과 된 한계이기 때문에 UWSGI 로그에는 오류가 나타나지 않습니다.

Nginx의 한계를 높이면 오류가 제거되었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top