Ruby的'open_uri'在读取或失败后是否可靠地关闭套接字?

yll*_*ate 5 ruby screen-scraping ruby-on-rails ruby-on-rails-3

我一直在使用open_uriftp路径作为数据源一段时间,但突然发现我几乎持续"530抱歉,允许的最大客户端数(95)已经连接."

我不确定我的代码是否有问题,或者是否是其他正在访问服务器的人,不幸的是我无法确切地知道谁有问题.

基本上我正在阅读FTP URI:

  def self.read_uri(uri)
    begin
      uri = open(uri).read
      uri == "Error" ? nil : uri
    rescue OpenURI::HTTPError
      nil
    end
  end
Run Code Online (Sandbox Code Playgroud)

我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,以便我的连接不是问题,但我认为open_uri + read将采取这种预防措施与使用Net :: FTP方法.

最重要的是,我必须100%确定这些连接正在关闭,而且我不会以某种方式打开一堆开放的连接.

有人可以建议正确使用read_uri拉入ftp并保证它正在关闭连接吗?或者我应该将逻辑转移到Net :: FTP,如果open_uri不够健壮,可以对情况产生更多控制?

如果我确实需要使用Net :: FTP方法,是否有一种我应该熟悉的读取方法,将其拉到tmp位置然后读取它(因为我更喜欢将它保存在缓冲区中)如果可能的话,与fs相比)?

the*_*Man 7

我怀疑你没有关闭手柄.OpenURI的文档从这个评论开始:

It is possible to open http/https/ftp URL as usual like opening a file:

open("http://www.ruby-lang.org/") {|f|
  f.each_line {|line| p line}
}
Run Code Online (Sandbox Code Playgroud)

我查看了源代码,open_uri如果传递一个块,方法会关闭流,因此,调整上面的示例以适合您的代码:

uri = ''
open("http://www.ruby-lang.org/") {|f|
  uri = f.read
}
Run Code Online (Sandbox Code Playgroud)

应该让你接近你想要的.


这是处理异常的一种方法:

# The list of URLs to pass in to check if one times out or is refused.
urls = %w[
  http://www.ruby-lang.org/
  http://www2.ruby-lang.org/
]

# the method
def self.read_uri(urls)

  content = ''

  open(urls.shift) { |f| content = f.read }
  content == "Error" ? nil : content

  rescue OpenURI::HTTPError
    retry if (urls.any?)
    nil
end
Run Code Online (Sandbox Code Playgroud)


pgu*_*rio 5

尝试使用块:

data = open(uri){|f| f.read}
Run Code Online (Sandbox Code Playgroud)