Як запобігти пошкодженню труби errno 32?


120

В даний час я використовую додаток, побудований в python. Коли я запускаю його в персональному комп’ютері, він працює без проблем.

Однак, коли я переміщу його на виробничий сервер. Він постійно показує мені помилку, що додається нижче:.

Я провів деякі дослідження, і я зрозумів, що браузер кінцевого користувача припиняє з'єднання, поки сервер все ще зайнятий надсиланням даних.

Цікаво, чому це сталося і яка першопричина, яка заважає йому належним чином працювати на виробничому сервері, поки він працює на моєму персональному комп’ютері. Будь-яка порада цінується

    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

Чи " це " вирішує ваше питання?
Пуреферрет

Або з'єднатися з uwsgi тощо.
KyungHoon Kim

Відповіді:


85

Ваш серверний процес отримав SIGPIPEзапис у сокет. Зазвичай це відбувається, коли ви пишете в повністю закритий сокет з іншого (клієнтського) боку. Це може статися, коли клієнтська програма не чекає, коли всі дані з сервера будуть отримані і просто закриє сокет (за допомогою closeфункції).

У програмі на C зазвичай ви намагаєтесь налаштувати ігнорувати SIGPIPEсигнал або встановити для нього фіктивний обробник сигналу. У цьому випадку проста проста помилка повернеться під час запису до закритого сокета. У вашому випадку пітон, здається, кидає виняток, який можна обробити як передчасне відключення клієнта.


2
Ось хороший відповідь на звернення клієнта роз'єднує: stackoverflow.com/a/180922/276274
Максим Skurydzin

9

Це залежить від того, як ви його протестували, та, можливо, від відмінностей у реалізації TCP-стеку персонального комп'ютера та сервера.

Наприклад, якщо ваш sendallзавжди завершується негайно (або дуже швидко) на персональному комп’ютері, підключення може просто ніколи не розірватися під час надсилання. Це дуже ймовірно, якщо ваш браузер працює на одній машині (оскільки немає реальної затримки в мережі).


Загалом, вам просто потрібно розглянути випадок, коли клієнт відключається, перш ніж закінчити, обробляючи виняток.

Пам’ятайте, що зв’язок TCP є асинхронним, але це набагато очевидніше на фізично віддалених підключеннях, ніж на локальних, тому такі умови, як цей, важко відтворити на локальній робочій станції. Зокрема, з'єднання із зворотним зв'язком на одній машині часто майже синхронні.


Я тестую його, виконуючи "paster serve abc.ini --reload", однак веб-сторінки так і не вдалося отримати. А для робочої станції VMWare я використовую лише варіант хоста для підключення до мережі. Тож чи можете ви порадити будь-який спосіб правильно запустити його?
SƲmmēr Aƥ

1
Я думаю, що це окремий запит на налаштування мережі VMWare (боюся, я нічого про це не знаю). Причина робочої станції і сервера можуть вести себе по- різному вище , хоча, і рішення тільки для обробки виключення зtry ... except
Даремні

7

Помилка розбитої труби зазвичай виникає, якщо ваш запит заблокований або триває занадто довго, і після таймауту на стороні запиту він перерве з'єднання і тоді, коли відповідна (сервер) спробує записати в сокет, вона викине помилка труби зламана.


3

Це може бути тому, що ви використовуєте два способи вставки даних у базу даних, і це спричиняє сповільнення роботи сайту.

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('/')

У наведеній вище функції помилка вказує на стрілку. Правильна реалізація наведена нижче:

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('/')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.