gpt4 book ai didi

python - 进程在 urllib2 套接字重置时挂起

转载 作者:行者123 更新时间:2023-11-28 16:35:32 26 4
gpt4 key购买 nike

我们有一个服务器程序偶尔会挂起在 read 调用上urllib2 连接重置时的套接字,如下所示:

Traceback (most recent call last):
File "run.py", line 112, in fetch_stuff
raw = response.read()
File "/usr/lib/python2.7/socket.py", line 351, in read
data = self._sock.recv(rbufsize)
File "/usr/lib/python2.7/httplib.py", line 573, in read
s = self.fp.read(amt)
File "/usr/lib/python2.7/socket.py", line 380, in read
data = self._sock.recv(left)
error: [Errno 104] Connection reset by peer

编辑:对于挂起,我的意思是程序没有崩溃并且在几个小时后仍然处于事件状态,但是,它似乎在打印了一条错误消息后仍然卡住了。

但是,据我所知,库句柄之外的代码句柄异常正确:

for i in range(retries):
try:
response = urllib2.urlopen(url)
raw = response.read() # fails here
...
except urllib2.HTTPError as e:
logging.error("HTTP Error for url=%s (code=%s, message=%s, headers=%s)" % (url, e.code, e.msg, e.hdrs))
except Exception as e:
logging.exception(e)
else:
logging.error(('Connection failed after {} tries').format(retries))
sys.exit(0)

我不明白为什么这会挂起整个过程进步。我们现在尝试将 timeout 参数设置为 urlopen,但我怀疑这能否解决问题。

那么,由于到目前为止我还没有找到有用的链接 (except maybe this answer),是否有一个(明显的)修复方法,我们是否应该使用另一个库,...?

此外,实际发生了什么?我知道连接已重置,但接下来会发生什么?

最佳答案

除非您在非阻塞套接字上工作,否则读取调用是阻塞的。因此,您的进程在调用 read() 时被阻塞。

由于某种原因,连接的另一端发送了一个设置了 RST 标志的数据包,关闭了连接。当操作系统检测到此事件时,recv 系统调用返回 ECONNRESET,定义在 linux/include/errno.h 中,对应于错误代码 104。

Python 使用 errno 模块 (https://docs.python.org/2/library/errno.html#module-errno) 翻译错误代码并引发异常。正如预期的那样,错误代码 104 是 errno.ECONNRESET:

>>> import errno
>>> print errno.ECONNRESET
104

然后您将捕获该异常并调用

logging.exception(e)

打印堆栈跟踪。之后,要么继续循环,要么跟随 else 分支。鉴于您的输出,我不清楚会发生什么。

这很容易重现。非常简单的客户端代码:

import urllib2
import logging

r = urllib2.urlopen("http://localhost:8080")
try:
print "Reading!"
r.read()
except Exception as e:
logging.exception(e)

在服务器端,直接从命令行:

➜  ~ [1] at 22:50:53 [Wed 12] $ nc -l -p 8080

一旦建立连接,客户端就会阻塞读取调用。一旦检测到某些流量,tcpkill 可用于通过 RST 标志终止连接:

~ [1] at 22:51:19 [Wed 12] $ sudo tcpkill -i lo port 8080

而且,正如预期的那样,客户端的结果是:

➜  ~ [1] at 23:12:37 [Wed 12] $ python m.py
Reading!
ERROR:root:[Errno 104] Connection reset by peer
Traceback (most recent call last):
File "m.py", line 7, in <module>
r.read()
File "/usr/lib/python2.7/socket.py", line 351, in read
data = self._sock.recv(rbufsize)
File "/usr/lib/python2.7/httplib.py", line 561, in read
s = self.fp.read(amt)
File "/usr/lib/python2.7/httplib.py", line 1302, in read
return s + self._file.read(amt - len(s))
File "/usr/lib/python2.7/socket.py", line 380, in read
data = self._sock.recv(left)
error: [Errno 104] Connection reset by peer

添加超时不会解决太多问题。如果您的连接被重置,而您的进程在读取调用时被阻止(即使有超时),结果将完全相同。我认为您应该首先尝试了解为什么要重置连接。但是,读取已使用 RST 标志关闭的套接字是一个您无法避免且应该处理的事件。

关于python - 进程在 urllib2 套接字重置时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26893870/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com