Project

General

Profile

Bug #11443

Updated by nemski (Patrick Robinson) over 8 years ago

On linux /etc/resolv.conf can be configured to set the timeout of a nameserver before trying the next one (defaults to 5 seconds). So in the event of a failed name server we expect the time taken to resolve a hostname will be timeout + query time. However testing shows it takes (2 * timeout) + query time. Example resolv.conf to replicate the problem of a failed name server: 

 ~~~ 
 nameserver 1.1.1.1 
 nameserver 8.8.8.8 
 nameserver 8.8.4.4 
 ~~~ 

 Example ruby code to test: 

 
 ``` 
 require 'net/protocol' 
 require 'uri' 
 require 'benchmark' 
 uri = URI.parse("http://google.com") 
 Benchmark.measure { TCPSocket.new(uri.host, uri.port) }.real 
 ``` 

 Example benchmark with a above resolv.conf: 

 ``` 
 irb(main):005:0> Benchmark.measure { TCPSocket.new(uri.host, uri.port) }.real 
 => 10.593100978 
 ``` 

 Example benchmark with timeout set to 3 in resolv.conf (options timeout:3): 

 ``` 
 irb(main):005:0> Benchmark.measure { TCPSocket.new(uri.host, uri.port) }.real 
 => 6.262138267 
 ``` 

 and without the invalid nameserver: 

 ``` 
 irb(main):005:0> Benchmark.measure { TCPSocket.new(uri.host, uri.port) }.real 
 => 0.243385728 
 ``` 

 Example C code that proves the resolver is behaving as expected: 

 ``` 
 #include <stdio.h> 
 #include <netdb.h> 

 int main(int argc, char *argv[]) 
 { 
     struct hostent *hstnm; 
     if (argc != 2) { 
         fprintf(stderr, "usage: %s hostname\n", argv[0]); 
         return 1; 
     } 
     hstnm = gethostbyname (argv[1]); 
     if (!hstnm) 
         return 1; 
     printf ("Name: %s\n", hstnm->h_name); 
     return 0; 
 } 
 ``` 

 Benchmark of C code with failed nameserver: 

 ~~~ 
 $ time ./gethostbyname google.com 
 Name: google.com 

 real 	 0m5.189s 
 user 	 0m0.000s 
 sys 	 0m0.000s 
 ~~~ 

 Benchmark of C code without failed nameserver: 

 ~~~ 
 $ time ./gethostbyname google.com 
 Name: google.com 

 real 	 0m0.040s 
 user 	 0m0.000s 
 sys 	 0m0.000s 
 ~~~

Back