首页 > 解决方案 > 请求 HTTPConnectionPool 读取超时永远不会恢复

问题描述

我有一个 24/7 运行的脚本,有时会被系统重启杀死。脚本的一部分从 pastebin[.]com 收集具有某些内容的垃圾箱,另一部分将它们导出到远程休息端点。我收集垃圾箱的部分发送了大量请求并且从不遇到问题HTTPConnectionPool,而另一部分往往很快就会遇到它,尽管它发送请求的频率要低得多。

我有以下带有重试逻辑的代码,因此我确保将 bin 导出到远程

def send_export_request(self, payload):
    while True:
        success = False
        try:
            self.session.post(self.collector, data=payload, timeout=10)
            success = True
        except requests.exceptions.RequestException as e:
            self.logger.log_error("RequestException ocurred when storing paste %s: %s" % (payload['key'], e))

        if success:
            break

        self.logger.log("Retrying to store the paste...")
        self.session.close()
        self.session = requests.session()
        sleep(2)

当然self.session是在构造函数中初始化为requests.session(). 最终总是会发生(时间量因情况而异,但总是在 24 小时内发生)是引发以下异常:

HTTPConnectionPool(host='www.[redacted].com', port=80): Read timed out. (read timeout=10)

代码进入循环,总是引发这个异常,记录它,等待2秒,再试一次,引发异常等等。它永远不会恢复,除非我杀死脚本并再次运行它。我搜索了很多,最初尝试了没有会话的代码(只是发布请求),然后添加了会话,最后尝试在重试之前创建新会话。这些都不起作用。我错过了什么?

标签: python-3.xpython-requestshttpconnection

解决方案


难怪没人知道问题出在哪里。我将回答这个问题以阐明问题所在。

我做了一些进一步的测试:我发布垃圾箱内容的远程服务器启用了某种 IPS 或类似系统。收集器不是(故意)在 HTTPS 之后,因此有效负载检查是可能的,当有效负载包含一些关键字或已知签名时,远程服务器决定让连接超时。

由于没有 HTTPS 背后的请求对我的用例至关重要(任何人都必须可以进行流量嗅探和检查),我想出了一个解决方法:如果请求被远程服务器杀死,我在重试之前对它的主体进行 base64 编码,然后它就可以工作了


推荐阅读