Ruby DNS 解析每隔一段时间就会挂起
Ruby DNS resolution hangs every other time
我有这段 ruby 间歇性工作的代码,当它挂起时,我可以在 shell 中多次调用它 ctrl-c-ing 并且它会立即工作一半时间永远挂着另一半。
require 'resolv'
puts "initializing"
txt = Resolv::DNS.open do |dns|
records = dns.getresources("www.google.com", Resolv::DNS::Resource::IN::A)
records.empty? ? nil : records.map{|rec| rec.address}.compact
end
puts "records are #{txt}"
这是我在两种情况下看到的输出
[ ~]$ ruby test.rb
initializing
records are 216.58.217.132
[ ~]$ ruby test.rb
initializing
records are 216.58.217.132
[ ~]$ ruby test.rb
initializing
^C/usr/lib/ruby/1.8/resolv.rb:620:in `select': Interrupt
from /usr/lib/ruby/1.8/resolv.rb:620:in `request'
from /usr/lib/ruby/1.8/resolv.rb:489:in `each_resource'
from /usr/lib/ruby/1.8/resolv.rb:975:in `resolv'
from /usr/lib/ruby/1.8/resolv.rb:973:in `each'
from /usr/lib/ruby/1.8/resolv.rb:973:in `resolv'
from /usr/lib/ruby/1.8/resolv.rb:972:in `each'
from /usr/lib/ruby/1.8/resolv.rb:972:in `resolv'
from /usr/lib/ruby/1.8/resolv.rb:970:in `each'
from /usr/lib/ruby/1.8/resolv.rb:970:in `resolv'
from /usr/lib/ruby/1.8/resolv.rb:481:in `each_resource'
from /usr/lib/ruby/1.8/resolv.rb:468:in `getresources'
from test.rb:4
from /usr/lib/ruby/1.8/resolv.rb:307:in `open'
from test.rb:3
我知道 DNS 是一项外部服务,它可能不稳定,但这并不能解释它为什么有时会立即工作而有时会永远挂起,而且,当我使用 host www.google.com
命令时它总是 returns 立即。
我怎样才能使这项工作按预期进行?
我试过你的代码,但无法重现问题。请注意,对于您的特定示例,响应并不总是相同的,这对 www.google.com
.
有意义
tmp> ruby resolv.rb
# initializing
# records are [#<Resolv::IPv4 216.58.211.100>]
tmp> ruby resolv.rb
# initializing
# records are [#<Resolv::IPv4 74.125.136.105>, #<Resolv::IPv4 74.125.136.106>, #<Resolv::IPv4 74.125.136.147>, #<Resolv::IPv4 74.125.136.99>, #<Resolv::IPv4 74.125.136.103>, #<Resolv::IPv4 74.125.136.104>]
我认为您遇到的问题出在您的代码之外。 host
命令比发出 DNS 请求多一点。它还检查 /etc/hosts
文件,并且可能涉及一些本地缓存。您应该尝试测试您的 DNS,也许使用 dig
命令,并检查答案是否真的总是来自 DNS 服务器,而不是缓存。
在您的代码中,您可能希望启用超时,例如:
dns.timeouts = 3
我有这段 ruby 间歇性工作的代码,当它挂起时,我可以在 shell 中多次调用它 ctrl-c-ing 并且它会立即工作一半时间永远挂着另一半。
require 'resolv'
puts "initializing"
txt = Resolv::DNS.open do |dns|
records = dns.getresources("www.google.com", Resolv::DNS::Resource::IN::A)
records.empty? ? nil : records.map{|rec| rec.address}.compact
end
puts "records are #{txt}"
这是我在两种情况下看到的输出
[ ~]$ ruby test.rb
initializing
records are 216.58.217.132
[ ~]$ ruby test.rb
initializing
records are 216.58.217.132
[ ~]$ ruby test.rb
initializing
^C/usr/lib/ruby/1.8/resolv.rb:620:in `select': Interrupt
from /usr/lib/ruby/1.8/resolv.rb:620:in `request'
from /usr/lib/ruby/1.8/resolv.rb:489:in `each_resource'
from /usr/lib/ruby/1.8/resolv.rb:975:in `resolv'
from /usr/lib/ruby/1.8/resolv.rb:973:in `each'
from /usr/lib/ruby/1.8/resolv.rb:973:in `resolv'
from /usr/lib/ruby/1.8/resolv.rb:972:in `each'
from /usr/lib/ruby/1.8/resolv.rb:972:in `resolv'
from /usr/lib/ruby/1.8/resolv.rb:970:in `each'
from /usr/lib/ruby/1.8/resolv.rb:970:in `resolv'
from /usr/lib/ruby/1.8/resolv.rb:481:in `each_resource'
from /usr/lib/ruby/1.8/resolv.rb:468:in `getresources'
from test.rb:4
from /usr/lib/ruby/1.8/resolv.rb:307:in `open'
from test.rb:3
我知道 DNS 是一项外部服务,它可能不稳定,但这并不能解释它为什么有时会立即工作而有时会永远挂起,而且,当我使用 host www.google.com
命令时它总是 returns 立即。
我怎样才能使这项工作按预期进行?
我试过你的代码,但无法重现问题。请注意,对于您的特定示例,响应并不总是相同的,这对 www.google.com
.
tmp> ruby resolv.rb
# initializing
# records are [#<Resolv::IPv4 216.58.211.100>]
tmp> ruby resolv.rb
# initializing
# records are [#<Resolv::IPv4 74.125.136.105>, #<Resolv::IPv4 74.125.136.106>, #<Resolv::IPv4 74.125.136.147>, #<Resolv::IPv4 74.125.136.99>, #<Resolv::IPv4 74.125.136.103>, #<Resolv::IPv4 74.125.136.104>]
我认为您遇到的问题出在您的代码之外。 host
命令比发出 DNS 请求多一点。它还检查 /etc/hosts
文件,并且可能涉及一些本地缓存。您应该尝试测试您的 DNS,也许使用 dig
命令,并检查答案是否真的总是来自 DNS 服务器,而不是缓存。
在您的代码中,您可能希望启用超时,例如:
dns.timeouts = 3