我们有一个进程(rake任务)运行很长一段时间,使用faraday和nethtpu持久适配器向远程主机发出https请求。运行几个小时到几天后,它停止发出请求。
该进程还使用excon(向我们的异常报告服务报告异常)发出一些请求,两个http客户端都记录了相同的错误,但措辞略有不同。这两个错误是:
法拉第::ssl error:ssl_connect syscall returned=5 errno=0 state=error:certificate verify failed
excon::error::certificate:ssl_connect syscall returned=5 errno=0 state=error:certificate verify failed(openssl::ssl::sslerror)无法验证证书。这可能是远程主机或excon的问题。excon捆绑了证书,但可以自定义这些证书:
我们的异常报告服务无法接收任何这些异常。所以我们只在日志中发现了这些错误。
最佳答案
为了重现这个问题,我运行了一个法拉第请求循环,直到它失败。我发现,虽然引发的异常是Faraday::SSLError
,但一旦我尝试在repl中执行需要打开文件的任何其他操作,它就会引发Errno::EMFILE: Too many open files
。
我终于有了线索。红鲱鱼是由于openssl库捕捉到EMFILE
系统错误,而引发了一般的ssl连接失败。法拉第和excon(由异常报告工具使用)都做到了这一点,使得我们无法看到真正的问题。
根本问题是进程已达到打开文件的限制。这是由the way that net-http-persistent keeps connections open until instructed to shut down加上Faraday has no mechanism to instruct its adapter to shut down的事实造成的。
解决方案是从net http persistent切换到excon,excon支持持久连接,只要配置为这样:
Faraday.new(url: url) do |faraday|
faraday.adapter :excon, persistent: true
end