如何防止客户端关闭连接时出现 'IOError: failed to write data'?

4 投票
2 回答
10315 浏览
提问于 2025-04-17 01:35

我有一个iPhone应用,它使用用Python编写的网络服务,这些服务是通过Django和Piston实现的,运行在通过WSGI连接的apache服务器上。

有时候,这个应用会在一个请求还没完成的时候就关闭与服务器的连接。这样一来,就会在我的服务器错误日志中出现:

[Tue Sep 06 11:29:46 2011] [error] [client 207.35.164.99] mod_wsgi (pid=820): Exception occurred processing WSGI script 'myscript.wsgi'.
[Tue Sep 06 11:29:46 2011] [error] [client 207.35.164.99] IOError: failed to write data

这样的错误信息。

我可以通过不主动关闭连接来“修复”这个问题,让它继续下载并忽略结果。不过,我希望能在服务器端解决这个问题,如果可以的话,我该怎么做呢?

2 个回答

1

看看这个链接:http://code.google.com/p/modwsgi/issues/detail?id=29

如果在处理可迭代对象时,系统会记录一条调试级别的信息,而不会抛出Python异常。因此,如果想要查看客户端关闭连接的问题,当使用可迭代对象时,需要将日志级别设置为调试。

显然,你需要调整你的Django响应,让它变成一个可迭代对象,而不是一个字符串。

7

[免责声明:这段内容是解释“为什么这件事不能轻易解决”,而不是给出解决方案]

正如@Slott所指出的,当在一个已经关闭的连接上调用stream.closestream.write时,这确实是技术上正确的行为。不过,我理解提问者的动机……在wsgi应用的上下文中,客户端在读取完或部分读取后就终止连接并不是“异常”行为,这种情况经常发生。如果不处理这种情况,就会给人一种这是意外的、代码没有做好准备的印象,实际上这是可以预见的,不应该特别提及。因此,解决这个问题会很不错。

问题在于,你需要找到一种方法来区分不同的情况……

  • 比如“客户端读取了‘状态:304’,然后关闭了连接”或“客户端读取了所有字节,然后关闭了连接,尽管它请求了连接应该被重用”,这些情况就适合不记录任何日志,除了log.debug()的调用。

  • 但是像“客户端在文件中途停止读取,因为连接在ISP路由器出现故障时中断”这样的情况就应该记录一个错误。这意味着某些操作没有成功完成,服务器应用程序建立的任何事务状态都应该被回滚。在这种情况下,IOError向上抛出是正确的做法。

这样的错误只有在每个可能引发错误的地方,代码被修改以区分这两种情况时,才能被“静默处理”。在此之前,wsgi的作者似乎选择了谨慎的做法。所以我知道的并没有快速的解决方案。


(另外,我应该指出这并不是django特有的,我使用paste+pylons时也会遇到同样的问题)

撰写回答