random technical thoughts from the Nominet technical team

Concurrency in DNS libraries

1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 4.33 out of 5)
Loading ... Loading ...
Posted by alexd on Jun 20th, 2007

I’ve been having a think about how the threading model should work in the dnsruby library (more on that in another post), and have been looking at those of other DNS libraries. I thought it might be useful to note them down here :

dnsjava

This library comes in layers. A SimpleResolver targets a single nameserver, performing no retries (other than normal TCP retries if appropriate). When a query is sent by a SimpleResolver, a new socket is opened and a new thread is fired up to handle the query (if asynchronous).

An ExtendedResolver sits on top of a collection of SimpleResolvers, with each one configured to communicate with a different nameserver. The ExtendedResolver then handles retries over different nameservers. Each query in each nameserver (and retried queries on the same nameserver) runs in a new thread on a new socket.

dnsjnio

dnsjnio is an extension to dnsjava that uses the java.nio library. It runs multiple queries in just 3 threads (one client, one select and one timer) over either a single or multiple ports. It allows heavy asynchronous use of the dnsjava library.

Net::DNS / pnet-dns

[pnet-dns is a Ruby port of perl’s Net::DNS and therefore has the same threading model]

These projects have a different approach to dnsjava. Instead of many resolver objects each speaking to a different nameserver in different threads, with one controlling thread handling retries, etc., the Net::DNS approach is to have everything related to a lookup run in one thread. However, with no asynchronous calls, you’d have to start a new query in a new thread if you wanted to run concurrent queries. You would also have to configure a Resolver specially if you wanted it to target a single nameserver with no retries (although this is possible).

Each time a new lookup query is issued, a new socket is opened by Net::DNS (unless a persistent socket is requested). This socket is then used in a select loop with timeouts. When a timeout occurs on a nameserver then a new query is sent, along with the next nameserver being tried, all on the same socket.

Ruby resolv.rb

This file is a pure Ruby DNS implementation. It can replace the OS calls made as standard by the language, thus bypassing the notorious “blocking lookup” problem. This problem occurs because all Ruby “threads” are in fact interpreter threads - so if one of them blocks on a system call, the whole of Ruby blocks.

This meant that native DNS lookup calls could grind the whole of Ruby to a halt. To avoid this, the resolv.rb library was written, which can be used by invoking :

require 'resolv-replace.rb'

The resolv.rb library is written in pure Ruby and allows the interpreter to continue whilst one thread is waiting for a response.

However, the library uses a single socket for each instance, which is not encouraged. I don’t think it could work if it were to use a different socket for each query, which will present a challenge for dnsruby.

It also provides no asynchronous calling mechanism, although different threads can be started to run different queries if desired.

Again, there is no mechanism to issue a single query packet (other a pathologically configured Resolv instance). The library will, by default, attempt retries over multiple nameservers (if configured).

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.

Recent Posts

Highest Rated

Categories

Archives

Meta: