Ruby DNS Caching

We use the rest-client gem in Ruby to automatically test our REST API. However, I noticed that for each individual query, it also does a DNS lookup for the hostname. In a local environment, if "localhost" is used, tests run quickly, but if the correct hostname is used, they take 2.5 times, making a huge amount of DNS queries.

I believe that this problem is not related, in particular, to the rest-client client, but the Ruby core network. I tried to require "resolv" and "resolv-replace", but they did not help. 'dig' reports that the DNS query has a TTL of 1 hour.

Is there a way to make Ruby DNS cache queries? I can change the code to explicitly use the IP address, but this is the wrong place to fix the problem.

I am running Ubuntu 12.04 and Ruby 1.9.3.

+3
source share
4 answers

I got to this question by looking for ruby ​​dns caching and how it resolv.rbcan use TTL to cache DNS queries.

Detecting a TTL dns entry is a bit hidden in the api resolv.rb, but it looks something like this:

def get_ip(hostname)
  dns = Resolv.new
  redis = Redis.new # storing in redis
  ip = redis.get("ip:#{hostname}") 
  return ip unless ip.nil?
  begin
    resource = dns.getresource(hostname, Resolv::DNS::Resource::IN::A)
  rescue Resolv::ResolvError
    return false
  end
  # storing in redis for only as long as the TTL allows
  redis.setex("ip:#{hostname}", resource.address.ttl, resource.address.to_s)
  resource.address.to_s # IP address as string
end

Gist

Note. The cache is Redis.

+1
source

I just looked at the rest-client code and it just uses Net :: HTTP, which in turn uses Socket.

Then everything disappears in the implementation of the Ruby interpreter, where my knowledge is a little weak (and the behavior may change depending on whether you use MRI, JRuby, etc.)

, DNS , , , ?

0

DNS, .

Ruby libc . , . libc.

, , - ip- , IP- .

SSL. .

, , Net:: HTTP DNS.

0

You can use the dnsruby gem to resolve a name to an address, and then use the address in your calls.

#! /usr/bin/env ruby

# Gets the IP address of a host.

require 'dnsruby'  # gem install dnsruby first, of course

def hostname_to_ip_addr(host_name)
  query = Dnsruby::Message.new(host_name)
  response = Dnsruby::Resolver.new.send_message(query)
  response.answer[1].address
end

host_name = 'cnn.com'
ip_addr = hostname_to_ip_addr(host_name)
puts("Host name: #{host_name}, IP address: #{ip_addr}")

source code from this gist

0
source

All Articles