Ruby Net::HTTP 执行已过期
Ruby Net::HTTP execution expired
使用 Net::HTTP,我定期发现下面的代码使用 "execution expired" 消息从 StandardError 中拯救出来,尽管来自访问 URL 的 Web 服务器日志显示相应的回复很快就发出来了。当 Web 服务器日志显示响应时间超过 5 秒时,我通常会看到来自 Timeout::Error.
的代码救援
什么情况下会导致下面的代码使用 "execution expired" 而不是 从 Timeout::Error 中拯救 StandardError?
这段代码是 运行 在一个相对古老的 Ruby 1.9.3 上的多线程程序中,在一个不支持较新版本 Ruby 的平台上。虽然该程序是多线程的,但显示的代码仅在单线程上运行。
begin
connection = Net::HTTP.new(uri.host, uri.port)
connection.open_timeout = 5
connection.read_timeout = 5
connection.start do |http|
request = Net::HTTP::Post.new("/reader_events")
request.body = body
response = http.request(request)
end
rescue StandardError => std_error
log "error sending event to server: #{std_error}"
rescue Timeout::Error => error
log "timeout sending event to server"
end
这是因为 rescue
的工作原理。查看 Exception
class 的文档页面。基本上你可以创建许多继承自单个异常的异常,并使用父 class:
的 rescue 处理所有异常
begin
...
rescue Exception => exception
...
end
此代码将拯救所有类型的异常,因为 Exception
是根(其他异常从它继承)。在你的情况下 Timeout::Error
继承自 RuntimeError
继承自 StandardError
:
Timeout::Error.ancestors
=> [Timeout::Error, RuntimeError, StandardError, Exception, Object, PP::ObjectMixin, Kernel, BasicObject]
结果有点像 Exception
:
Timeout::Error.new.is_a?(StandardError)
=> true
你的情况的另一件事是解释器将从上到下检查每个 rescue
语句。这意味着首先它会检查 exception
是否属于 StandardError
类型,然后它会移动到下面的 rescue
块。您应该始终列出 rescue
个块,从最具体到最一般。
更改 rescue
个块的顺序以修复代码。
使用 Net::HTTP,我定期发现下面的代码使用 "execution expired" 消息从 StandardError 中拯救出来,尽管来自访问 URL 的 Web 服务器日志显示相应的回复很快就发出来了。当 Web 服务器日志显示响应时间超过 5 秒时,我通常会看到来自 Timeout::Error.
的代码救援什么情况下会导致下面的代码使用 "execution expired" 而不是 从 Timeout::Error 中拯救 StandardError?
这段代码是 运行 在一个相对古老的 Ruby 1.9.3 上的多线程程序中,在一个不支持较新版本 Ruby 的平台上。虽然该程序是多线程的,但显示的代码仅在单线程上运行。
begin
connection = Net::HTTP.new(uri.host, uri.port)
connection.open_timeout = 5
connection.read_timeout = 5
connection.start do |http|
request = Net::HTTP::Post.new("/reader_events")
request.body = body
response = http.request(request)
end
rescue StandardError => std_error
log "error sending event to server: #{std_error}"
rescue Timeout::Error => error
log "timeout sending event to server"
end
这是因为 rescue
的工作原理。查看 Exception
class 的文档页面。基本上你可以创建许多继承自单个异常的异常,并使用父 class:
begin
...
rescue Exception => exception
...
end
此代码将拯救所有类型的异常,因为 Exception
是根(其他异常从它继承)。在你的情况下 Timeout::Error
继承自 RuntimeError
继承自 StandardError
:
Timeout::Error.ancestors
=> [Timeout::Error, RuntimeError, StandardError, Exception, Object, PP::ObjectMixin, Kernel, BasicObject]
结果有点像 Exception
:
Timeout::Error.new.is_a?(StandardError)
=> true
你的情况的另一件事是解释器将从上到下检查每个 rescue
语句。这意味着首先它会检查 exception
是否属于 StandardError
类型,然后它会移动到下面的 rescue
块。您应该始终列出 rescue
个块,从最具体到最一般。
更改 rescue
个块的顺序以修复代码。