Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching DNS queries in Ruby

Tags:

caching

ruby

dns

We are using the rest-client gem in Ruby for automated testing of our REST API. However I noticed that on every single request it makes, it also does a DNS lookup for the host name. On the local environment if "localhost" is used the tests run fast, but if the proper hostname is used they take 2.5x the time, performing a huge number of DNS lookups.

I believe this issue is not related to rest-client in particular, but the base Ruby networking. I tried requiring '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 cache DNS requests? I could change the code to explicitly use the IP address, but that's the wrong place to fix the issue.

I'm running Ubuntu 12.04 and Ruby 1.9.3.

like image 671
Sampo Avatar asked May 15 '12 08:05

Sampo


People also ask

Does Linux cache DNS entries?

On Linux, there is no OS-level DNS caching unless a caching service such as Systemd-Resolved, DNSMasq, or Nscd is installed and running. The process of clearing the DNS cache is different depending on the Linux distribution and the caching service you're using.

Where is DNS cache in Linux?

Show activity on this post. If you are using nscd , you can view the contents (and possibly some other garbage), by showing the ASCII strings from the binary cache file. In Debian/Ubuntu, that file is /var/cache/nscd/hosts for the hosts/DNS cache, so you can run strings /var/cache/nscd/hosts to see the hosts in cache.

How disable DNS cache Linux?

Disable DNS CacheLog in to your system with the user has sudo privileges and Edit NetworkManager configuration file in your favorite text editor. Now comment the following entry by added # symbol to start of line like below. Save the configuration file. Vi users use ESC + :wq to save file and quit.


2 Answers

You can use the dnsruby gem to resolve the 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}")

original code from this Gist

like image 97
Keith Bennett Avatar answered Sep 28 '22 09:09

Keith Bennett


I got to this question looking for ruby dns caching and how resolv.rb might use the TTL to cache dns requests.

Discovering the TTL of a dns record is a bit hidden in the api of resolv.rb but it looks a little 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: uses Redis as the cache.

like image 25
bcromie Avatar answered Sep 28 '22 07:09

bcromie