Sam*_*a K 4 python python-requests
我有这个简单的代码,它与外部服务器连接。我称这个函数为每分钟 100 秒。一段时间后,我收到系统缺少足够缓冲区的异常。当我使用 TCPView 查看连接时,它显示数百个到外部服务器的连接处于 TIME_WAIT 状态。
如果我要发送100个请求,那么python request模块不适合吗?那我该怎么办?
def sendGetRequest(self, url, payload):
success = True
url = self.generateUrl(url)
result = requests.get(url, params=urllib.parse.urlencode(payload))
code = result.status_code
text = result.text
if code < 200 or code >= 300:
success = False
result.close()
return success, code, text
Run Code Online (Sandbox Code Playgroud)requests 您正在关闭在客户端打开的许多连接,而服务器希望重新使用它们。
由于HTTP是TCP协议,是一种双向协议,在客户端关闭套接字意味着套接字还不能完全关闭,直到另一端(服务器端)确认连接已正确关闭。在与服务器交换确认之前(或者直到超时,设置为达到最大段生存期的 2 倍),套接字将保持在该TIME_WAIT状态。在 HTTP 中,关闭通常发生在服务器端,响应完成后;服务器将等待您的客户端确认关闭。
您会看到很多这样的内容,因为每个新连接都必须使用新的本地端口号。服务器不会遇到几乎相同的问题,因为它对传入请求使用固定端口号,并且即使可能存在任意数量的未完成连接状态,该单个端口号也可以接受更多连接TIME_WAIT。另一方面,大量本地传出端口TIME_WAIT意味着您最终将用完可连接的本地端口。
这并不是 Python 或requests.
相反,您应该做的是最小化连接数量并最小化关闭。现代 HTTP 服务器期望您为多个请求重用连接。您想要使用一个requests.Session()对象,因此它可以为您管理连接,然后不要自己关闭连接。
您还可以通过使用标准功能来大大简化您的功能requests;params例如,已经处理了 url 编码,并且比较已经为您提供了一个可以直接分配给的布尔值success:
session = requests.Session()
def sendGetRequest(self, url, payload):
result = session.get(self.generateUrl(url), params=payload)
success = 200 <= result.status_code < 300
return success, result.status_code, result.text
Run Code Online (Sandbox Code Playgroud)
请注意,3xx状态代码已经自动处理,因此您可以使用response.ok:
def sendGetRequest(self, url, payload):
result = session.get(self.generateUrl(url), params=payload)
return result.ok, result.status_code, result.text
Run Code Online (Sandbox Code Playgroud)
接下来,您可能需要考虑使用asyncio协程(并且aiohttp仍然使用会话)来发出所有这些检查请求。这样,您的代码不必在每次请求-响应往返完成时都处于空闲状态,而是可以在该间隔期间执行其他操作。我构建的应用程序可以毫不费力地一次处理 1000 个并发 HTTP 请求,同时在缓慢的网络 I/O 操作完成的同时执行大量有意义的操作。
| 归档时间: |
|
| 查看次数: |
3599 次 |
| 最近记录: |