稳健地调用不稳定的 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 进行正确的错误处理 的相关文章

  • 如何从 Ruby 检查具有特定 pid 的进程是否正在运行?

    如果有多种方法 请列出 我只知道一个 但我想知道是否有一种更干净的 Ruby 方式 之间的区别Process getpgid and Process kill方法似乎是当 pid 存在但由另一个用户拥有时发生的情况 Process getp
  • WCF 未在 IIS 6.0 下运行

    尝试让我的 WCF 服务在 IIS 6 下运行 我已经创建了 svc and aspnet isapi dll映射根据 http msdn microsoft com en us library ms752241 aspx http msd
  • HTTP部分上传、断点续传的标准方法

    我正在开发 http 客户端 服务器框架 并寻找处理部分上传的正确方法 与使用带有 Range 标头的 GET 方法进行下载相同 但是 HTTP PUT 并不打算恢复 据我所知 PATCH 方法不接受 Range 标头 有没有办法通过 HT
  • 回形针如何更改基本名称(文件名)?

    我正在尝试更改照片的基本名称 文件名 在我的模型中我有 attr accessor image url basename has attached file image styles gt original gt 300x250 gt pn
  • 如何处理用户界面中的数据库约束违规?

    我们使用存储过程在数据库中实现大部分业务规则 我永远无法决定如何最好地将数据约束违规错误从数据库传递回用户界面 我所说的约束更多地与业务规则相关 而不是与数据完整性相关 例如 诸如 无法插入重复的键行 之类的数据库错误与业务规则 不能有多个
  • 在新的 RHEL6 服务器上安装 ruby​​-filemagic gem 时遇到困难

    它似乎正在寻找 libmagic so 1 文件 我有那个文件 它位于 usr lib64 中 我没有以 root 用户身份运行此安装 我也在使用 rvm 和 Bundler 这是我的 bundle 命令的结果 当它到达 Gemfile 中
  • BigDecimal 无法强制转换为 BigDecimal

    这应该很简单 但它却爆炸了 有任何想法吗 d BigDecimal new 2 0 YAML load a gt d to yaml TypeError BigDecimal can t be coerced into BigDecimal
  • Chrome 在传输一定量的数据后挂起 - 等待可用的套接字

    我有一个浏览器游戏 最近我开始向游戏添加音频 Chrome 无法加载整个页面并卡在 91 requests 8 1 MB transferred 并且不再加载任何内容 它甚至破坏了所有其他选项卡中的网站 说Waiting for avail
  • Ruby:在 Ubuntu 上安装 rmagick

    我正在尝试在 Ubuntu 10 04 上安装 RMagick 看起来here https stackoverflow com questions 1482823 is there an easy way to install rmagic
  • 如何从数组中删除空白元素?

    我有以下数组 cities Kathmandu Pokhara Dharan Butwal 我想从数组中删除空白元素并想要以下结果 cities Kathmandu Pokhara Dharan Butwal 有没有类似的方法compact
  • 在 ruby​​ 中读/写受密码保护和加密的文件

    我想加密一个 ruby 程序将从中加载数据的文件 此外 我需要程序在启动时提示输入密码 该密码将用于解密文件 换句话说 该文件需要加密地驻留在计算机上 只有拥有密码的用户才能运行该应用程序 我已经开始研究 openpgp 但据我了解 这仍然
  • 在golang中获取TTFB(第一个字节的时间)值

    我正在尝试获取 TTFB 值和 Connect 值 c exec Command curl w Connect time connect TTFB time starttransfer Total time time total o dev
  • 由于浏览器设置的标头,Safari 拒绝重定向的 CORS 请求

    Summary Safari 拒绝一些涉及重定向的 CORS 请求 声称某些标头是不允许的 但该标头从来不是由脚本请求的 而是由浏览器添加的 所以我认为这应该不重要 Safari 的行为是一个错误吗 规格有问题吗 或者 事情变成这样是有原因
  • HTTP代理服务器

    我开始研究一个用 C 编写的非常基本的 HTTP 代理服务器 Edit 只是转发我的请求的东西 此时我很难理解如何继续 任何帮助都会有益的 看一眼micro proxy http acme com software micro proxy
  • 返回重定向作为对 Ajax(fetch、XHR 等)请求的响应

    如果浏览器收到对 ajax 请求的重定向响应 会发生什么 如果浏览器收到对 ajax 请求的重定向响应 会发生什么 如果服务器发送重定向 又名 302 响应加上 Location 标头 浏览器将自动遵循重定向 对此的回应second请求 假
  • 为什么静态方法不能用作 ASMX Web 服务中的 Web 服务操作?

    我只是想了解为什么我不能在 Web 服务中使用静态 Web 方法 为什么会受到限制 有人可以给我对此进行简洁的解释吗 答案是 因为你不能 它不是这样设计的 其设计是 将创建 Web 服务类的实例 然后调用实例方法 我只能猜测微软为什么这样设
  • 使用复选框过滤列表

    我有一个电影列表及其评级 在我的页面顶部 我有一个表单 其中提供了一个复选框列表 其中显示了每个可用的评级 G PG 13 等 一旦用户单击复选框并点击提交 我只想显示所选的电影 在我的索引方法中 我有一个名为的实例变量 filtered
  • 当会话令牌无效时,我应该使用什么状态代码?

    创建 Web 服务 RESTful 时 当会话令牌无效时我应该使用什么状态代码 目前我公司的人给我发了一个404 未找到 但我认为这是不正确的 因为资源存在 也许我应该使用 401 Unauthorized 你怎么认为 您建议我在这种情况下
  • 有没有办法通过API调用访问私有数据集

    我正在使用 CKAN 2 8 运行 Mirth 3 6 1 作为新手 我遇到了一个问题 有没有办法通过 API 请求访问 CKAN 中私有数据集中的资源 我好像做不到 我有一个拥有公共数据集的组织 我可以通过 API 路由器通过 Mirth
  • 在 RESTful Web 服务中实现注销

    我正在开发一个需要注销服务的移动应用程序 登录服务是通过数据库验证来完成的 现在我陷入了注销状态 退一步 您没有提供有关如何在应用程序中执行身份验证的详细信息 并且很难猜测您在做什么 但是 需要注意的是 在 REST 应用程序中 不能有会话

随机推荐