稳健地调用不稳定的 API:使用 Net::HTTP 进行正确的错误处理

2024-03-30

我将其组合在一起,作为一种看似强大的方式来调用一个不稳定的 Web 服务,该服务会出现超时和偶尔的名称解析或套接字错误或其他问题。 我想我应该把它放在这里,以防它有用,或者更有可能的是,被告知更好的方法来做到这一点。

require 'net/http'

retries = 5
begin
  url = URI.parse('http://api.flakywebservice.com')
  http = Net::HTTP.new(url.host, url.port)
  http.read_timeout = 600  # be very patient
  res = nil
  http.start{|http|
    req = Net::HTTP::Post.new(url.path)
    req.set_form_data(params)  # send a hash of the POST parameters
    res = http.request(req)
  }
rescue Exception   # should really list all the possible http exceptions
  sleep 3
  retry if (retries -= 1) > 0
end

# finally, do something with res.body, like JSON.parse(res.body)

这个问题的核心是: 当调用这样的网络服务时,我应该寻找哪些异常? 这里尝试收集所有这些,但似乎必须有比这更好的方法:http://tammersaleh.com/posts/rescuing-net-http-exceptions http://tammersaleh.com/posts/rescuing-net-http-exceptions


例外是有意义的,并且Net::HTTP针对不同类型的情况提供特定的例外情况。因此,如果您想以特定的方式处理它们,您可以。

那篇文章说,处理这些特定的异常比处理更好/更安全rescue Exception,这是非常正确的。但,rescue Exception不同于rescue就其本身而言,这相当于rescue StandardError,如果您没有理由做任何其他事情,那么默认情况下您通常应该这样做。

拯救高层Exception将挽救整个执行堆栈中可能发生的任何情况,包括 ruby​​ 的某些部分耗尽磁盘或内存或出现一些与系统相关的模糊 IO 问题。

因此,就“要拯救什么”而言,如果将代码更改为,通常情况会更好rescue。你会抓住你想要的一切,而不会抓住你不想要的。然而,在这种特殊情况下,该人的列表中有一个例外,它不是 StandardError 的后代:

def parents(obj)
  ( (obj.superclass ? parents(obj.superclass) : []) << obj)
end

[Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse,
  Net::HTTPHeaderSyntaxError, Net::ProtocolError].inject([]) do |a,c|
  parents(c).include?(StandardError) ? a : a << c
end
# Timeout::Error < Interrupt

parents(Timeout::Error)
# [ Object, Exception < Object, SignalException < Exception,
#   Interrupt < SignalException, Timeout::Error < Interrupt ]

所以你可以将你的代码更改为rescue StandardError, Timeout::Error => e您将涵盖该文章中提到的所有情况以及更多内容,但不会涵盖您不想涵盖的内容。 (这=> e不是必需的,但更多内容如下)。

现在,就您处理 Flakey API 的实际技术而言,问题是,您正在处理的 API 存在什么问题?回复格式错误?没有回应?问题是在 HTTP 级别还是在您返回的数据中?

也许您还不知道,或者您还不关心,但您知道重试往往会完成工作。在这种情况下,我至少建议记录异常。Hoptoad https://hoptoadapp.com/account/new?source=home_top_button有一个免费计划,并且有类似的东西Hoptoad.notify(e)——我不记得这是否是准确的调用。或者您可以使用电子邮件发送或记录它e.message and e.stacktrace.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

稳健地调用不稳定的 API:使用 Net::HTTP 进行正确的错误处理 的相关文章

随机推荐