我的问题与How to rescue timeout issues (Ruby, Rails)有关。
以下是从超时中解救的常用方法:
def action
# Post using Net::HTTP
rescue Timeout::Error => e
# Do something
end
我想确定在尝试连接到主机时是否引发了异常,或者是否在尝试从主机读取时引发异常。这可能吗?
答案 0 :(得分:11)
这是解决方案(在Ben的修复之后):
require "net/http"
http = Net::HTTP.new("example.com")
http.open_timeout = 2
http.read_timeout = 3
begin
http.start
begin
http.request_get("/whatever?") do |res|
res.read_body
end
rescue Timeout::Error
puts "Timeout due to reading"
end
rescue Timeout::Error
puts "Timeout due to connecting"
end
答案 1 :(得分:0)
如果你不能升级到ruby 2.x,Marc-AndréLafortune的解决方案仍然是最好的。
从2.x开始,将引发Timeout::Error
的子类,具体取决于触发的超时:
Net::OpenTimeout
Net::ReadTimeout
但是,read_timeout
行为在2.x上很奇怪,因为它似乎会使您设置的值加倍。
这是两个超时的测试(在1.8.7,1.9.3,2.1.2,2.2.4上测试)。
编辑:open_timeout测试适用于Mac,但在Linux上,客户端收到“连接被拒绝”错误。
require "net/http"
require "socket"
SERVER_HOST = '127.0.0.1'
SERVER_PORT = 9999
def main
puts 'with_nonlistening_server'
with_nonlistening_server do
make_request
end
puts
puts 'with_listening_server'
with_listening_server do
make_request
end
end
def with_listening_server
# This automatically starts listening
serv = TCPServer.new(SERVER_HOST, SERVER_PORT)
begin
yield
ensure
serv.close
end
end
def with_nonlistening_server
raw_serv = Socket.new Socket::AF_INET, Socket::SOCK_STREAM, 0
addr = Socket.pack_sockaddr_in SERVER_PORT, SERVER_HOST
# Bind, but don't listen
raw_serv.bind addr
begin
yield
ensure
raw_serv.close
end
end
def make_request
http = Net::HTTP.new(SERVER_HOST, SERVER_PORT)
http.open_timeout = 1
http.read_timeout = 1 # seems to be doubled on ruby 2.x
start_tm = Time.now
begin
http.start
begin
http.get('/')
rescue Timeout::Error => err
puts "Read timeout: #{err.inspect}"
end
rescue Timeout::Error => err
puts "Open timeout: #{err.inspect}"
end
end_tm = Time.now
puts "Duration (sec): #{end_tm - start_tm}"
end
if __FILE__ == $PROGRAM_NAME
main
end
1.9.3上的示例输出:
with_nonlistening_server
Open timeout: #<Timeout::Error: execution expired>
Duration (sec): 1.002477
with_listening_server
Read timeout: #<Timeout::Error: Timeout::Error>
Duration (sec): 1.00599
2.1.2上的示例输出:
with_nonlistening_server
Open timeout: #<Net::OpenTimeout: execution expired>
Duration (sec): 1.005923
with_listening_server
Read timeout: #<Net::ReadTimeout: Net::ReadTimeout>
Duration (sec): 2.009582