我正在构建一个基本的负载生成器并开始遇到文件描述符限制,我还没有看到任何有关如何释放资源的文档,因此我做错了,文档需要更新,或者请求在某个地方泄漏了文件描述符(无支持)对于keepalive,我对为什么所有文件都保持打开状态感到有些困惑)
您在哪里使用requests.async
?
是的,所有请求都是合理的普通requests.get / requests.post,我仍然在其中看到一些
$ lsof | grep localhost | wc -l
110
除了4/5以外的所有格式
Python 82117 daleharvey 123u IPv4 0xffffff800da304e0 0t0 TCP localhost:61488->localhost:http (CLOSE_WAIT)
老实说,我对此感到困惑。
如果我不能近距离拍摄,哈哈请再拍一次以可靠地复制它
我已经看到这种情况发生在我身上,但是只有当我使用带有200多个同时连接的异步模块时,这种情况才会发生。
你好
使用gevent进行请求和猴子修补时,我遇到了完全相同的问题:一些连接停留在CLOSE_WAIT中。
gevent可能是个问题。
这可能是ulimit -n的问题。 尝试更高的价值。
“套接字打开过多”是由于套接字停留在CLOSE_WAIT中导致的错误的结果。
因此,ulimit不能仅仅通过解决办法来解决。
@tamiel我们如何解决这个问题?
我将尽快进行更多测试并尝试修复。
我已经研究过了,似乎所有使用httplib.HTTPSConnection的库都存在问题。
在此处发布示例:
我只是在使用仅具有HTTP连接的异步池时遇到了非常相似的错误-我仍在调查,但是将池大小传递给async.map会使错误迅速重现。
有任何解决办法吗? 这使得Requests无法与gevent一起使用。
全部与CLOSE_WAIT
s有关。 只需关闭它们。 我不确定为什么他们仍然开放。
是urllib3问题吗? 我觉得必须自己关闭这些不是一个好主意。
这更是一个普遍的问题。 我们可以在这里保持对话。
好的,只是为了给您一个视角,我们正在尝试从httplib2转到请求,并且我们看不到httplib2出现此问题。 因此,这肯定不是一个普遍的问题。
一般而言,我的意思是这是一个非常严重的问题,影响到每个相关人员。
那么我们该如何解决呢? 我们真的很想使用请求+继续沉睡
我很想知道答案。
该泄漏似乎是由于内部重定向处理所致,该内部重定向处理导致在使用未决响应之前生成新请求。 在测试中, acdha @ 730c0e2e2bef77968a86962f9d5f2bebba4d19ec的满意度不足,但有效的解决方法是仅在继续操作之前强制使用每个响应。
这需要在两个地方进行更改,这使我想稍微重构一下接口,但是目前没有时间继续。
使用异步时遇到了相同的问题-通过分块请求并删除响应/调用gc.collect来浪费时间
我相信我今天遇到的问题是连接到仅允许5个连接的许可服务器。
使用异步,我只能在暂停60秒之前获取4件事。
使用普通的GET消耗,我可以在40秒内连续获取约150个东西。
自从我看到这个问题以来,还没有做出决定。
刚在使用ipython时收到此错误,并收到了此消息。 这只是一次发出每个请求,但是我认为使用异步时我得到了类似的东西。
ERROR: Internal Python error in the inspect module.
Below is the traceback from this internal error.
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/IPython/core/ultratb.py", line 756, in structured_traceback
File "/Library/Python/2.7/site-packages/IPython/core/ultratb.py", line 242, in _fixed_getinnerframes
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 1035, in getinnerframes
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 995, in getframeinfo
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 456, in getsourcefile
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 485, in getmodule
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 469, in getabsfile
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py", line 347, in abspath
OSError: [Errno 24] Too many open files
Unfortunately, your original traceback can not be constructed.
奇怪的是,我认为当仅使用普通的Python解释器时,我会收到“最大重试错误”,但我认为这是我在所有相同域上执行请求的另一个问题,但不确定。
我在我的第一个项目中遇到了这个问题,其中allow_redirects为True; 它似乎是由重定向链泄漏响应对象引起的,即使使用prefetch = True也不会释放该对象。 这在我的初始测试中已解决:
[i.raw.release_conn() for i in resp.history]
resp.raw.release_conn()
嗯..
@acdha设置:
requests.defaults.defaults['allow_redirects'] = False
在我发出任何请求之前,仍然会导致相同的错误,但是我认为这对于我的实现来说不是一个选择,因为我正在发出的所有请求都将需要重定向= /
@dalanmiller您如何处理您的回复? 我以前使用的是带有响应挂钩的async.map
,它通过在async.imap
进行简单循环而_appears_更加稳定:
for resp in requests.async.imap(reqs, size=8):
try:
print resp.status_code, resp.url
finally:
[i.raw.release_conn() for i in resp.history]
resp.raw.release_conn()
@acdha
我只是在URL列表中使用for循环,并使用我的设置等对每个对象执行request.get。
for u in urls:
response_list.append(requests.get(u))
我尝试使用您的粘贴,它可在900个长度列表中处理大约50个请求,直到剩下的时间开始出现“超出url的最大重试错误”为止。 尽管这是一个相当标准的错误,但是对于重复击中相同的域来说,不是吗?
嘿,我正在抓取大量的URL(35k),并且在_some_的请求中遇到了同样的错误。
我得到的网址是10个大块,像这样:
responses = requests.async.map([requests.async.get(u, params=self.params()) for u in chunk]) # chunk is a list of 10
在20k范围内的某个地方,我开始出现错误24,然后通过30k正常,然后再次出现。
您是否有兴趣进一步缩小范围?
requests.async
不见了。 您可能要考虑转向grequests。
好的,谢谢。 最好在文档中提及这一点。
在拉取请求和编写文档方面有点菜鸟,但我对此一口气把它寄了出去。 请发表评论或批评:)
好的,即使在6K请求之后,仅使用request.get而不使用异步,也会发生这种情况。
我怀疑。
对我来说,完全下载1k文件后出现“打开文件过多”错误。 我的解决方案是禁用keep-alive属性,以获取成块的请求( @acdha感谢您的提示)。 lsof -p PID | wc -l
表示执行期间连接的数量没有增加。
rsess = requests.session()
rsess.config['keep-alive'] = False
rs = [grequests.get(l, session=rsess) for l in links]
for s in chunks(rs,100):
responses = grequests.map(s, size=concurrency)
for r in responses:
try:
print(r.status_code, r.url)
finally:
r.raw.release_conn()
[1]分块: http :
在推迟到urllib3修复的同时关闭。
@kennethreitz urllib3的发行号是什么?
@silvexis很可能与urllib3错误有关,现在我只是希望有人回答了@ piotr-dobrogost:P
还有其他人遇到这个问题吗?
我还没有听到任何报道。 你是?
这是盒子配置的问题,而不是框架的问题。 查看操作系统的内核配置。 在BSD中,它称为kern.maxfiles
。 在Linux系统中有大约ulimit
线程: http :
希望对您有所帮助,并且我不知道如何在Windows上更改此参数。
需要注意的是,我们仍在运行旧版本的请求,因此我们准备了以下可怕的代码来处理此问题:
if self._current_response is not None:
# Requests doesn't have a clean API to actually close the
# socket properly. Dig through multiple levels of private APIs
# to close the socket ourselves. Icky.
self._current_response.raw.release_conn()
if self._current_response.raw._fp.fp is not None:
sock = self._current_response.raw._fp.fp._sock
try:
logger.debug('Forcibly closing socket')
sock.shutdown(socket.SHUT_RDWR)
sock.close()
except socket.error:
pass
(我认为self._current_response是请求的响应对象)
嗯,关闭链在哪里断了? 我们有一个Response.close()
方法调用release_conn()
,那么在release_conn()
中需要做什么才能起作用?
@Lukasa,这绝对是在urllib3中修复的,因为我是讨论的一部分。 我倾向于保守一点,我想说的是,因为请求1.2.x甚至不是1.1.x。
是的,我确实认为这是固定的。 除非我们在1.2.3上看到任何内容,否则我将继续假设此问题已解决。
我看到使用2.0.2的CLOSE_WAIT泄漏,您是否进行了单元测试以确保对该主题不进行回归?
不,我们不。 AFAIK urllib3也没有。 您可以轻松重现泄漏吗?
自周一以来,我们在内部应用中使用request,今天已达到1024个maxfile。
重新启动2小时后,lsof告诉我们40 CLOSE_WAIT。
因此,我认为我们将能够在开发环境中进行复制。 我会与你保持联系
还@tardyp ,您如何安装请求? 我认为所有OS软件包维护者都应删除urllib3。 如果他们没有保持最新状态,而您使用的是旧版本,则可能是原因。 如果您使用的是pip,请随时打开一个新问题来跟踪,而不是在此问题上进行讨论。
我安装了pip,但我使用的是python 2.6,我已经看到针对python2.7的修复
这个错误。 您是否为较旧版本打上补丁?
皮埃尔
在2013年11月29日,星期五,下午5:33,Ian Cordasco [email protected] :
@tardyp https://github.com/tardyp ,您如何安装请求? 一世
认为所有OS软件包维护者都将urllib3删除了。 如果他们不这样做
保持最新状态,而您使用的是旧版本,则可能是
原因。 如果您使用的是点子,请随时打开一个新的问题来
跟踪此内容,而不是对此添加讨论。-
直接回复此电子邮件或在Gi tHub上查看它
。
@tardyp,请尽可能详细地打开一个新问题,包括您发出的请求是否具有重定向以及是否正在使用gevent。 同样,关于操作系统的任何细节以及如何重现该操作系统的示例都是很棒的。
仅供参考,由于错误, https://github.com/shazow/urllib3/issues/291已恢复。
我们应该重新打开吗?
我有相同的问题!
@polvoazul不可能是同一问题,该问题最初是在2011年报告的,所以我认为重新开放是不正确的。 但是,如果您正在运行当前版本的请求(2.4.3)并且可以重现该问题,则打开一个新的问题将是正确的。
@Lukasa我需要您的帮助。我使用eventlet +请求,总是会创建很多无法识别协议的袜子。我的请求是2.4.3,eventlet +请求会导致此问题吗?
对不起, @ mygoda ,但是这是不可能的。 如果您不限制任何一次可以处理的请求数量,那么肯定有可能,但这是请求范围之外的体系结构问题。
现在遇到相同的问题,运行120个线程,导致100000+个打开的文件,现在有什么解决方案?
@mygoda,你用了不起的时期。
@ 1a1a11a _您打开了哪些文件? 这将是理解此问题的有用的第一步。
@ 1a1a11a您使用的是什么版本的请求? 什么版本的python? 什么操作系统? 我们可以获得任何信息吗?
我正在使用请求2.9.1,python 3.4,ubuntu 14.04,基本上我正在编写使用30个带有代理的线程来搜寻某些网站的搜寻器。 目前,我已将每个进程的文件限制调整为655350,否则它将报告错误。
我仍然收到来自request.packages.urllib3.connection.VerifiedHTTPSConnection的错误“无法建立新的连接:[Errno 24]打开的文件太多”。我正在使用Python 3.4、2.11.1和请求- 0.9.7。我很欣赏requests-futures是一个单独的库,但是错误似乎来自请求。我正尝试通过SSL发出180k异步请求。我已将这些请求分为1000个段,所以我仅在解决所有将来的对象后才移至下一个1000。我正在运行Ubuntu 16.04.2,默认的打开文件数限制为1024。了解此错误的根本原因是很好的。每个单独的请求都打开文件?如果是,为什么?这是SSL证书文件吗?当将来的对象解析时,请求库是否会自动关闭那些打开的文件?
请求会打开许多文件。 其中一些文件是为证书打开的,但是它们是由OpenSSL而不是由Requests打开的,因此这些文件不会得到维护。 此外,如果需要,请求也会打开.netrc
文件,hosts文件以及许多其他文件。
使用strace
类的工具来确定打开了哪些文件,将为您提供最好的服务。 有严格的系统调用列表,这些文件会导致分配文件描述符,因此您应该有足够的能力快速枚举它们。 这也将使您知道是否存在问题。 但是,是的,我希望如果您通过HTTPS主动建立1000个连接,那么在峰值负载下,我们可以轻松使用1000个以上的FD。
我也为这个问题而苦苦挣扎,发现在OS X上使用opensnoop
很好地让我看到如果有人遇到相同的问题会发生什么。
当重复调用requests.post(url, data=data)
到HTTP
(不是HTTPS)服务器时,我也经常看到此错误。 在Ubuntu 16.04.3,Python 3.5.2上运行,请求2.9.1
什么是data
?
几百kb的文字
不是文件对象?
不,我在内存中形成一个大查询。
您是否在多个线程中运行此代码?
不,单线程,发布到本地主机
对于我们来说,要泄漏那么多FD似乎几乎是不可能的:我们应该重复使用相同的TCP连接或主动关闭它。 想检查您的服务器在做什么吗?
我有这个问题。 Python 2.7,要求2.18.4,urllib3 1.22。
运行多线程代码(不是多进程的)。 一次最多连接6个URL,手动为每个URL创建和关闭一个新会话。
我在Python 3.5
, requests==2.18.4
上遇到相同的问题
@mcobzarenco您确定要(隐式)关闭响应的基础连接吗? 仅返回响应不会关闭连接。 当读取response.content时,实际上是在读取数据,此后套接字将不会停留在CLOSE_WAIT中。
最有用的评论
“套接字打开过多”是由于套接字停留在CLOSE_WAIT中导致的错误的结果。
因此,ulimit不能仅仅通过解决办法来解决。