如何防止errno 32破损的管道?

183

目前我使用的是用 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

这个链接是否解决了你的问题? - AncientSwordRage
或者连接到uwsgi等。 - KyungHoon Kim
6个回答

119

您的服务器进程在向套接字写入数据时接收到了 SIGPIPE 信号。这通常发生在您向已完全关闭的(客户端)另一端的套接字写入数据时。这可能会发生在客户端程序没有等待从服务器接收所有数据,而是简单地关闭了套接字(使用 close 函数)的情况下。

在 C 程序中,通常会尝试设置忽略 SIGPIPE 信号或为其设置虚拟信号处理程序。在这种情况下,当向关闭的套接字写入数据时,将返回一个简单的错误。在您的情况下,Python 似乎会抛出一个异常,可以将其视为客户端的早期断开连接。


2
这里有一个关于处理客户端断开连接的好答案:https://dev59.com/LHVC5IYBdhLWcg3wz0h9#180922 - Maksim Skurydzin

25

破损的管道错误通常发生在您的请求被阻止或耗时太长且超过了请求端的超时时间后,它将关闭连接。然后,在响应端(服务器)尝试写入套接字时,将会抛出一个管道破损错误。


我想用一个请求在Google Sheets上上传太多的数据。将数据集减半后,它成功了。 - Chris

10

这取决于你如何进行测试,可能还涉及到个人电脑和服务器TCP堆栈实现的差异。

例如,如果你的sendall在个人电脑上总是立即完成(或者非常快地完成),那么连接可能只是在发送过程中从未断开。如果你的浏览器运行在同一台机器上(因为没有真正的网络延迟),这很有可能发生。


通常,你只需要处理客户端在完成之前断开连接的情况,通过处理异常来实现。

请记住,TCP通信是异步的,但这在物理上远程的连接上比在本地连接上更加明显,因此这种情况在本地工作站上很难重现。具体来说,在单台机器上的回环连接往往是几乎同步的。


1
我正在运行“paster serve abc.ini --reload”进行测试,但是网页始终无法访问。对于VMWare Workstation,我正在使用Host-only选项进行网络连接。所以您能否请教任何正确运行它的方法? - SƲmmēr Aƥ
1
我认为那是一个单独的VMWare网络配置问题(恐怕我对此一无所知)。然而,工作站和服务器可能表现不同的原因已经在上面解释了,解决方案就是使用 try ... except 处理异常。 - Useless

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

1

在你的程序顶部尝试使用这段代码:

from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE,SIG_DFL)

它应该解决这个问题。

6
目前你的回答写得不清楚。请[编辑]以添加更多细节,帮助其他人理解这如何回答所提出的问题。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

0
如果是Python Web应用程序或服务,例如Flask或FastAPI,则此错误可能会发生,如果生产服务器配置为超时处理时间过长的请求。 Gunicorn和Uvicorn中有相关参数,例如GRACEFUL_TIMEOUT和TIMEOUT,需要根据您的应用程序的需求进行配置。 您还可以检查反向代理或网关超时阈值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接