Марк-Андре Lafortune по-прежнему лучше всего, если вы не можете обновить до рубинового 2.x.
Начиная с версии 2.x, подкласс Timeout::Error
будет увеличен в зависимости от времени ожидания был вызван:
Net::OpenTimeout
Net::ReadTimeout
Однако read_timeout
поведение странно на 2 .x, потому что он, кажется, удваивает значение, которое вы установили.
Вот тест для обоих тайм-аутов (проверен на 1.8.7, 1.9.3, 2.1.2, 2.2.4).
EDIT: тест 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
Марк, я действительно хочу, чтобы это было правдой, но это не работает для меня , Я думаю, что это потому, что 'http.request_get' создает и использует новый экземпляр« Net :: HTTP », который не наследует переменные таймаута. –
Я беру это обратно, он не создает новый экземпляр «Net: HTTP». Тем не менее, кажется, что тайм-аут составляет около 30 секунд независимо от того, что я установил для открытия и чтения таймаутов. –
open_timeout работает для меня, на обоих рубинах 1.8.7 и 1.9.2 dev. Трудно протестировать read_timeout, и это может быть прочитано в блоке, вы должны проверить код. Тем не менее, если вы поместите оба значения в 0,1, это должно быть слишком быстро, нет? В любом случае, мой ответ по-прежнему является правильным способом отличить то, что вызвало таймаут! –