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