Jak zapobiec pęknięciu rury ERRNO 32?

120

Obecnie używam aplikacji wbudowanej w Pythonie. Kiedy uruchamiam go na komputerze osobistym, działa bez problemów.

Jednak kiedy przenoszę go na serwer produkcyjny. Ciągle pokazuje mi załączony błąd jak poniżej:

Zrobiłem kilka badań i znalazłem powód, dla którego przeglądarka użytkownika końcowego zatrzymuje połączenie, gdy serwer nadal jest zajęty wysyłaniem danych.

Zastanawiam się, dlaczego tak się stało i jaka jest podstawowa przyczyna, która uniemożliwia mu prawidłowe działanie na serwerze produkcyjnym, podczas gdy działa na moim komputerze osobistym. Każda rada jest mile widziana

    Exception happened during processing of request from ('127.0.0.1', 34226)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 284, in
_handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 310, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 641, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 694, in finish
    self.wfile.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
SƲmmēr Aƥ
źródło
Czy to „rozwiązuje” Twój problem?
Pureferret
Lub połącz się z uwsgi itp.
KyungHoon Kim

Odpowiedzi:

85

Twój proces serwera otrzymał SIGPIPEzapis do gniazda. Zwykle dzieje się tak, gdy piszesz do gniazda całkowicie zamkniętego po drugiej stronie (klienta). Może się tak zdarzyć, gdy program klienta nie czeka na odebranie wszystkich danych z serwera i po prostu zamyka gniazdo (za pomocą closefunkcji).

W programie w C normalnie próbowałbyś ustawić ignorowanie SIGPIPEsygnału lub ustawić dla niego fałszywą obsługę sygnału. W takim przypadku podczas zapisu do zamkniętego gniazda zostanie zwrócony prosty błąd. W twoim przypadku Python wydaje się rzucać wyjątek, który można potraktować jako przedwczesne rozłączenie klienta.

Maksim Skurydzin
źródło
2
Oto dobra odpowiedź dotycząca obsługi rozłączeń klienta: stackoverflow.com/a/180922/276274
Maksim Skurydzin
9

Zależy to od tego, jak go przetestowałeś i prawdopodobnie od różnic w implementacji stosu TCP na komputerze osobistym i serwerze.

Na przykład, jeśli sendallzawsze kończysz natychmiast (lub bardzo szybko) na komputerze osobistym, połączenie może po prostu nigdy nie zostać zerwane podczas wysyłania. Jest to bardzo prawdopodobne, jeśli Twoja przeglądarka działa na tym samym komputerze (ponieważ nie ma rzeczywistego opóźnienia sieci).


Ogólnie rzecz biorąc, wystarczy obsłużyć przypadek, w którym klient rozłącza się przed zakończeniem, obsługując wyjątek.

Pamiętaj, że komunikacja TCP jest asynchroniczna, ale jest to znacznie bardziej oczywiste w przypadku połączeń zdalnych fizycznie niż lokalnych, więc takie warunki mogą być trudne do odtworzenia na lokalnej stacji roboczej. W szczególności połączenia pętli zwrotnej na jednym komputerze są często prawie synchroniczne.

Bezużyteczny
źródło
Testuję go, uruchamiając polecenie „paster serv abc.ini --reload”, jednak nigdy nie udało się uzyskać dostępu do tej strony. W przypadku stacji roboczej VMWare używam opcji tylko host do połączenia sieciowego. Czy możesz więc uprzejmie doradzić jakikolwiek sposób, aby go poprawnie uruchomić?
SƲmmēr Aƥ
1
Myślę, że to osobne pytanie dotyczące konfiguracji sieci VMWare (obawiam się, że nic o tym nie wiem). Powodem stacja robocza i serwer mogą zachowywać się inaczej, choć jest wyżej, a rozwiązanie jest po prostu obsłużyć wyjątek ztry ... except
Useless
7

Błąd zepsutego potoku zwykle występuje, jeśli żądanie jest zablokowane lub trwa zbyt długo i po przekroczeniu limitu czasu po stronie żądania zamknie połączenie, a następnie, gdy strona odpowiedzi (serwer) spróbuje zapisać do gniazda, wyrzuci błąd zerwanej rury.

Aaren Shar
źródło
3

Może to być spowodowane tym, że używasz dwóch metod wstawiania danych do bazy danych, co powoduje spowolnienie witryny.

def add_subscriber(request, email=None):
    if request.method == 'POST':
        email = request.POST['email_field']
        e = Subscriber.objects.create(email=email).save()  <==== 
        return HttpResponseRedirect('/')
    else:
        return HttpResponseRedirect('/')

W powyższej funkcji błąd jest tam, gdzie wskazuje strzałka. Prawidłowa implementacja jest poniżej:

def add_subscriber(request, email=None):
    if request.method == 'POST':
        email = request.POST['email_field']
        e = Subscriber.objects.create(email=email)
        return HttpResponseRedirect('/')
    else:
        return HttpResponseRedirect('/')
Kuldeep K. Rishi
źródło