6 votes

Mise en cache des requêtes DNS en Ruby

Nous utilisons la gemme rest-client en Ruby pour les tests automatisés de notre API REST. Cependant, j'ai remarqué qu'à chaque demande qu'il fait, il effectue également une recherche DNS pour le nom de l'hôte. Dans l'environnement local, si "localhost" est utilisé, les tests se déroulent rapidement, mais si le nom d'hôte approprié est utilisé, ils prennent 2,5 fois plus de temps, en effectuant un grand nombre de recherches DNS.

Je pense que ce problème n'est pas lié à rest-client en particulier, mais au réseau Ruby de base. J'ai essayé de demander 'resolv' et 'resolv-replace' mais cela n'a rien donné. dig " indique que la requête DNS a un TTL de 1 heure.

Existe-t-il un moyen de faire en sorte que Ruby mette en cache les requêtes DNS ? Je pourrais modifier le code pour utiliser explicitement l'adresse IP, mais ce n'est pas le bon endroit pour résoudre le problème.

J'utilise Ubuntu 12.04 et Ruby 1.9.3.

2voto

Keith Bennett Points 21

Vous pouvez utiliser la gemme dnsruby pour résoudre le nom en une adresse, puis utiliser l'adresse dans vos appels.

#! /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}")

code original de ce Gist

2voto

bcromie Points 21

Je suis arrivé à cette question en cherchant la mise en cache des DNS par ruby et comment resolv.rb pourrait utiliser le TTL pour mettre en cache les requêtes DNS.

La découverte du TTL d'un enregistrement dns est un peu cachée dans l'api de resolv.rb mais ça ressemble un peu à ça :

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 : utilise Redis comme cache.

1voto

Gabe Points 133

Le système d'exploitation fournit généralement une certaine mise en cache des noms DNS, mais elle n'est pas toujours activée.

D'après ce que j'ai compris, ruby utilise libc pour résoudre les noms. Cela pourrait donc mettre en cache les réponses par processus. Je ne suis pas tout à fait sûr de la libc, cependant.

Une solution de contournement possible consiste à résoudre manuellement le nom d'hôte en adresse IP dans votre programme ruby, puis à utiliser l'adresse IP renvoyée pour des demandes répétées aux mêmes hôtes.

Cependant, cela peut ne pas fonctionner aussi bien pour les connexions aux cibles SSL. La validation du certificat dépend souvent de la correspondance avec un nom d'hôte.

Il existe peut-être une belle gemme ruby network socket qui n'utilise pas Net::HTTP et garde son propre cache DNS.

0voto

Andy Triggs Points 708

Je viens de jeter un coup d'oeil au code du rest-client et il utilise simplement Net::HTTP, qui à son tour utilise Socket.

Ensuite, tout disparaît dans l'implémentation de l'interpréteur Ruby, où mes connaissances sont un peu faibles (et le comportement changera peut-être selon que vous utilisez MRI, JRuby, etc.)

Je m'attendrais à ce que la résolution DNS soit confiée au système d'exploitation, donc peut-être que votre problème est dû à une configuration étrange du résolveur sur l'hôte ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X