在RoR中,如果我没有得到服务器的响应,如何捕获异常?

时间:2016-07-14 21:37:15

标签: ruby ruby-on-rails-4 open-uri no-response

我正在使用Rails 4.2.3和Nokogiri从网站获取数据。当我没有从服务器得到任何响应时,我想执行一个动作,所以我有:

begin
  content = open(url).read
  if content.lstrip[0] == '<'
    doc = Nokogiri::HTML(content)
  else
    begin
      json = JSON.parse(content)
    rescue JSON::ParserError => e
      content
    end
  end
rescue Net::OpenTimeout => e
  attempts = attempts + 1
  if attempts <= max_attempts
    sleep(3)
    retry
  end
end

请注意,这与从服务器获取500不同。我只想在没有响应的情况下重试,因为我没有得到TCP连接,或者因为服务器没有响应(或者其他一些原因导致我没有得到任何响应)。除了我的方式之外,还有更通用的方法来考虑这种情况吗?我觉得我还没有想到很多其他异常类型。

3 个答案:

答案 0 :(得分:4)

这是一个通用示例,您可以如何定义HTTP连接的超时持续时间,并在获取内容(编辑)时出现任何错误时执行多次重试

require 'open-uri'
require 'nokogiri'

url = "http://localhost:3000/r503"

openuri_params = {
  # set timeout durations for HTTP connection
  # default values for open_timeout and read_timeout is 60 seconds
  :open_timeout => 1,
  :read_timeout => 1,
}

attempt_count = 0
max_attempts  = 3
begin
  attempt_count += 1
  puts "attempt ##{attempt_count}"
  content = open(url, openuri_params).read
rescue OpenURI::HTTPError => e
  # it's 404, etc. (do nothing)
rescue SocketError, Net::ReadTimeout => e
  # server can't be reached or doesn't send any respones
  puts "error: #{e}"
  sleep 3
  retry if attempt_count < max_attempts
else
  # connection was successful,
  # content is fetched,
  # so here we can parse content with Nokogiri,
  # or call a helper method, etc.
  doc = Nokogiri::HTML(content)
  p doc
end

答案 1 :(得分:4)

在拯救例外方面,您应该明确了解:

  • 系统中的哪些行可以引发异常
  • 当这些代码行运行
  • 时,幕后发生了什么
  • 底层代码可以引发哪些具体异常

在您的代码中,获取内容的行也是可以看到网络错误的行:

content = open(url).read

如果您转到documentation for the OpenURI module,您会看到它使用Net::HTTP&amp;朋友们获取任意URI的内容。

确定Net::HTTP可以提出的内容实际上非常复杂,但幸运的是,其他人已经为您完成了这项工作。 Thoughtbot的吊杆项目有lists of common network errors你可以使用。请注意,其中一些错误与您考虑的网络条件不同,例如重置连接。我认为值得拯救这些产品,但请随意根据您的具体需求进行调整。

所以这里的代码应该是什么样的(跳过Nokogiri和JSON部分来简化一些事情):     要求&#39; net / http&#39;     要求&#39; open-uri&#39;

HTTP_ERRORS = [
  EOFError,
  Errno::ECONNRESET,
  Errno::EINVAL,
  Net::HTTPBadResponse,
  Net::HTTPHeaderSyntaxError,
  Net::ProtocolError,
  Timeout::Error,
]
MAX_RETRIES = 3

attempts = 0

begin
  content = open(url).read
rescue *HTTP_ERRORS => e
  if attempts < MAX_RETRIES
    attempts += 1
    sleep(2)
    retry
  else
    raise e
  end
end

答案 2 :(得分:1)

我会考虑使用Timeout在短时间内引发异常:

tappedViewOverlay