3

我们有一个长时间运行的进程(Rake 任务),使用 Faraday 和 net_http_persistent 适配器向远程主机发出 HTTPS 请求。在运行几个小时到几天后,它会停止发出请求。

该过程还使用 Excon 发出一些请求(向我们的异常报告服务报告异常),并且两个 HTTP 客户端都记录了相同的错误,但措辞略有不同。这两个错误是:

Faraday::SSLError: SSL_connect SYSCALL returned=5 errno=0 state=error: 证书验证失败

Excon::Error::Certificate: SSL_connect SYSCALL returned=5 errno=0 state=error: 证书验证失败 (OpenSSL::SSL::SSLError) 无法验证证书。这可能是远程主机或 Excon 的问题。Excon 捆绑了证书,但可以自定义:

我们的异常报告服务没有收到任何这些异常。所以我们只在日志中发现了这些错误。

4

1 回答 1

2

为了重现这个问题,我运行了一个法拉第请求循环,直到它失败。我发现,虽然引发的异常是Faraday::SSLError,但一旦我尝试在 REPL 中执行任何其他需要打开文件的操作,它就会引发Errno::EMFILE: Too many open files.

我终于有了线索。红鲱鱼是由 OpenSSL 库捕获EMFILE系统错误引起的,而不是引发一般的 SSL 连接失败。Faraday 和 Excon(由异常报告工具使用)都这样做了,因此无法看到真正的问题。

根本问题是该进程已达到打开文件的限制。这是由于net-http-persistent 保持连接打开直到被指示关闭的方式以及法拉第没有机制来指示其适配器关闭的事实引起的。

解决方案是从 net-http-persistent 切换到 Excon,只要它被配置为支持持久连接:

Faraday.new(url: url) do |faraday|
  faraday.adapter :excon, persistent: true
end
于 2019-07-26T04:12:30.397 回答