วิธีป้องกันท่อแตก errno 32?


121

ตอนนี้ฉันใช้แอพที่สร้างขึ้นใน 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

ไม่นี้ 'แก้' ปัญหาของคุณหรือไม่
Pureferret

หรือเชื่อมต่อกับ uwsgi ฯลฯ
KyungHoon Kim

คำตอบ:


85

กระบวนการเซิร์ฟเวอร์ของคุณได้รับการSIGPIPEเขียนลงในซ็อกเก็ต สิ่งนี้มักเกิดขึ้นเมื่อคุณเขียนลงในซ็อกเก็ตที่ปิดสนิทที่ด้านอื่น (ไคลเอนต์) สิ่งนี้อาจเกิดขึ้นเมื่อโปรแกรมไคลเอนต์ไม่รอจนกว่าจะได้รับข้อมูลทั้งหมดจากเซิร์ฟเวอร์และเพียงแค่ปิดซ็อกเก็ต (โดยใช้closeฟังก์ชัน)

ในโปรแกรม C ปกติคุณจะลองตั้งค่าให้ละเว้นSIGPIPEสัญญาณหรือตั้งค่าตัวจัดการสัญญาณหลอก ในกรณีนี้ข้อผิดพลาดทั่วไปจะถูกส่งกลับเมื่อเขียนลงในซ็อกเก็ตแบบปิด ในกรณีของคุณงูหลามดูเหมือนจะโยนข้อยกเว้นที่สามารถจัดการได้เป็นการตัดการเชื่อมต่อไคลเอนต์ก่อนเวลาอันควร


2
นี่คือคำตอบที่ดีเกี่ยวกับการจัดการการตัดการเชื่อมต่อไคลเอนต์: stackoverflow.com/a/180922/276274
Maksim Skurydzin

9

ขึ้นอยู่กับว่าคุณทดสอบอย่างไรและอาจเป็นไปได้จากความแตกต่างในการใช้งาน TCP stack ของคอมพิวเตอร์ส่วนบุคคลและเซิร์ฟเวอร์

ตัวอย่างเช่นหากคุณsendallมักจะดำเนินการเสร็จสิ้นในทันที (หรือเร็วมาก) บนคอมพิวเตอร์ส่วนบุคคลการเชื่อมต่ออาจไม่ขาดระหว่างการส่ง เป็นไปได้มากถ้าเบราว์เซอร์ของคุณทำงานบนเครื่องเดียวกัน (เนื่องจากไม่มีเวลาแฝงของเครือข่ายจริง)


โดยทั่วไปคุณต้องจัดการกับกรณีที่ไคลเอนต์ตัดการเชื่อมต่อก่อนที่จะดำเนินการเสร็จสิ้นโดยจัดการข้อยกเว้น

โปรดจำไว้ว่าการสื่อสาร TCP เป็นแบบอะซิงโครนัส แต่สิ่งนี้ชัดเจนกว่าในการเชื่อมต่อระยะไกลทางกายภาพมากกว่าการเชื่อมต่อแบบโลคัลดังนั้นเงื่อนไขเช่นนี้จึงยากที่จะทำซ้ำบนเวิร์กสเตชันท้องถิ่น โดยเฉพาะการเชื่อมต่อแบบย้อนกลับบนเครื่องเดียวมักจะเป็นแบบซิงโครนัสเกือบทั้งหมด


ฉันกำลังทดสอบโดยเรียกใช้ "paster serve abc.ini --reload" แต่ไม่สามารถเข้าถึงหน้าเว็บได้ และสำหรับ VMWare Workstation ฉันกำลังใช้ตัวเลือกเฉพาะโฮสต์สำหรับการเชื่อมต่อเครือข่าย คุณช่วยแนะนำวิธีเรียกใช้อย่างถูกต้องได้ไหม
SƲmmērAƥ

1
ฉันคิดว่านั่นเป็นคำถามการกำหนดค่าเครือข่าย VMWare ที่แยกจากกัน (ฉันกลัวว่าจะไม่รู้อะไรเลย) เหตุผลเวิร์กสเตชันและเซิร์ฟเวอร์อาจทำงานแตกต่างกันอยู่เหนือแม้ว่าและวิธีการแก้ปัญหาเป็นเพียงการจัดการข้อยกเว้นด้วยtry ... except
เปล่าดาย

8

ข้อผิดพลาดของท่อแตกมักเกิดขึ้นหากคำขอของคุณถูกบล็อกหรือใช้เวลานานเกินไปและหลังจากหมดเวลาฝั่งคำร้องจะปิดการเชื่อมต่อจากนั้นเมื่อฝ่ายตอบกลับ (เซิร์ฟเวอร์) พยายามเขียนลงในซ็อกเก็ตคำขอจะส่ง ข้อผิดพลาดท่อแตก


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('/')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.