请求 HTTPConnectionPool 读取超时永远不会恢复

Requests HTTPConnectionPool Read timeout never recovers

我有一个 运行 24/7 的脚本,有时会被系统重启杀死。一部分脚本从 pastebin[.]com 收集包含特定内容的 bin,另一部分将它们导出到远程 rest 端点。我收集垃圾箱的部分发送了很多请求并且从不遇到 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 秒,重试,引发异常等等。它永远不会恢复,除非我杀死脚本并再次 运行 它。我搜索了很多,最初尝试了没有会话的代码(只有 post 请求),然后添加了会话,最后尝试在重试之前创建新会话。 None 有效。我错过了什么?

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

我做了一些进一步的测试:我将垃圾箱内容发布到的远程服务器启用了某种 IPS 或类似系统。 Collector 并非(有意)支持 HTTPS,因此可以进行负载检查,并且当负载包含一些关键字或已知签名时,远程服务器决定让连接超时。

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