在 RoR 中,如果我没有得到服务器的响应,我该如何捕获异常?
In RoR, how do I catch an exception if I get no response from a server?
我正在使用 Rails 4.2.3 和 Nokogiri 从网站获取数据。我想在服务器没有任何响应时执行一个操作,所以我有:
begin
content = open(url).read
if content.lstrip[0] == '<'
doc = Nokogiri::HTML(content)
else
begin
json = JSON.parse(content)
rescue JSON::ParserError => e
content
end
end
rescue Net::OpenTimeout => e
attempts = attempts + 1
if attempts <= max_attempts
sleep(3)
retry
end
end
请注意,这与从服务器获取 500 不同。我只想在完全没有响应时重试,要么是因为我没有 TCP 连接,要么是因为服务器无法响应(或者其他一些导致我得不到任何响应的原因)。除了我的情况,是否有更通用的方法来考虑这种情况?我觉得还有很多我没有想到的其他异常类型。
这是一个通用示例,您可以如何定义 HTTP 连接的超时持续时间,并在获取内容时发生任何错误时执行多次重试(已编辑)
require 'open-uri'
require 'nokogiri'
url = "http://localhost:3000/r503"
openuri_params = {
# set timeout durations for HTTP connection
# default values for open_timeout and read_timeout is 60 seconds
:open_timeout => 1,
:read_timeout => 1,
}
attempt_count = 0
max_attempts = 3
begin
attempt_count += 1
puts "attempt ##{attempt_count}"
content = open(url, openuri_params).read
rescue OpenURI::HTTPError => e
# it's 404, etc. (do nothing)
rescue SocketError, Net::ReadTimeout => e
# server can't be reached or doesn't send any respones
puts "error: #{e}"
sleep 3
retry if attempt_count < max_attempts
else
# connection was successful,
# content is fetched,
# so here we can parse content with Nokogiri,
# or call a helper method, etc.
doc = Nokogiri::HTML(content)
p doc
end
我会考虑使用 Timeout 在短时间后引发异常:
MAX_RESPONSE_TIME = 2 # seconds
begin
content = nil # needs to be defined before the following block
Timeout.timeout(MAX_RESPONSE_TIME) do
content = open(url).read
end
# parsing `content`
rescue Timeout::Error => e
attempts += 1
if attempts <= max_attempts
sleep(3)
retry
end
end
说到拯救异常,你的目标应该是清楚地了解:
- 您系统中的哪些行可以引发异常
- 当这些代码行 运行
时,幕后发生了什么
- 底层代码可以引发哪些特定异常
在您的代码中,获取内容的行也是可能出现网络错误的行:
content = open(url).read
如果您转到 documentation for the OpenURI module,您会看到它使用 Net::HTTP
& friends 来获取任意 URI 的内容。
弄清楚 Net::HTTP
可以筹集的资金实际上非常复杂,但值得庆幸的是,其他人已经为您完成了这项工作。 Thoughtbot 的吊带项目有 lists of common network errors 可供您使用。请注意,其中一些错误与您所想的不同的网络条件有关,例如连接被重置。我认为也值得拯救它们,但请随意 trim 根据您的具体需求列出清单。
所以你的代码应该是这样的(跳过 Nokogiri 和 JSON 部分来简化一些事情):
需要 'net/http'
需要 'open-uri'
HTTP_ERRORS = [
EOFError,
Errno::ECONNRESET,
Errno::EINVAL,
Net::HTTPBadResponse,
Net::HTTPHeaderSyntaxError,
Net::ProtocolError,
Timeout::Error,
]
MAX_RETRIES = 3
attempts = 0
begin
content = open(url).read
rescue *HTTP_ERRORS => e
if attempts < MAX_RETRIES
attempts += 1
sleep(2)
retry
else
raise e
end
end
我正在使用 Rails 4.2.3 和 Nokogiri 从网站获取数据。我想在服务器没有任何响应时执行一个操作,所以我有:
begin
content = open(url).read
if content.lstrip[0] == '<'
doc = Nokogiri::HTML(content)
else
begin
json = JSON.parse(content)
rescue JSON::ParserError => e
content
end
end
rescue Net::OpenTimeout => e
attempts = attempts + 1
if attempts <= max_attempts
sleep(3)
retry
end
end
请注意,这与从服务器获取 500 不同。我只想在完全没有响应时重试,要么是因为我没有 TCP 连接,要么是因为服务器无法响应(或者其他一些导致我得不到任何响应的原因)。除了我的情况,是否有更通用的方法来考虑这种情况?我觉得还有很多我没有想到的其他异常类型。
这是一个通用示例,您可以如何定义 HTTP 连接的超时持续时间,并在获取内容时发生任何错误时执行多次重试(已编辑)
require 'open-uri'
require 'nokogiri'
url = "http://localhost:3000/r503"
openuri_params = {
# set timeout durations for HTTP connection
# default values for open_timeout and read_timeout is 60 seconds
:open_timeout => 1,
:read_timeout => 1,
}
attempt_count = 0
max_attempts = 3
begin
attempt_count += 1
puts "attempt ##{attempt_count}"
content = open(url, openuri_params).read
rescue OpenURI::HTTPError => e
# it's 404, etc. (do nothing)
rescue SocketError, Net::ReadTimeout => e
# server can't be reached or doesn't send any respones
puts "error: #{e}"
sleep 3
retry if attempt_count < max_attempts
else
# connection was successful,
# content is fetched,
# so here we can parse content with Nokogiri,
# or call a helper method, etc.
doc = Nokogiri::HTML(content)
p doc
end
我会考虑使用 Timeout 在短时间后引发异常:
MAX_RESPONSE_TIME = 2 # seconds
begin
content = nil # needs to be defined before the following block
Timeout.timeout(MAX_RESPONSE_TIME) do
content = open(url).read
end
# parsing `content`
rescue Timeout::Error => e
attempts += 1
if attempts <= max_attempts
sleep(3)
retry
end
end
说到拯救异常,你的目标应该是清楚地了解:
- 您系统中的哪些行可以引发异常
- 当这些代码行 运行 时,幕后发生了什么
- 底层代码可以引发哪些特定异常
在您的代码中,获取内容的行也是可能出现网络错误的行:
content = open(url).read
如果您转到 documentation for the OpenURI module,您会看到它使用 Net::HTTP
& friends 来获取任意 URI 的内容。
弄清楚 Net::HTTP
可以筹集的资金实际上非常复杂,但值得庆幸的是,其他人已经为您完成了这项工作。 Thoughtbot 的吊带项目有 lists of common network errors 可供您使用。请注意,其中一些错误与您所想的不同的网络条件有关,例如连接被重置。我认为也值得拯救它们,但请随意 trim 根据您的具体需求列出清单。
所以你的代码应该是这样的(跳过 Nokogiri 和 JSON 部分来简化一些事情): 需要 'net/http' 需要 'open-uri'
HTTP_ERRORS = [
EOFError,
Errno::ECONNRESET,
Errno::EINVAL,
Net::HTTPBadResponse,
Net::HTTPHeaderSyntaxError,
Net::ProtocolError,
Timeout::Error,
]
MAX_RETRIES = 3
attempts = 0
begin
content = open(url).read
rescue *HTTP_ERRORS => e
if attempts < MAX_RETRIES
attempts += 1
sleep(2)
retry
else
raise e
end
end