Let’s face it, with all of the data service APIs that exist in today’s marketplace, the applications we build might need to make one or more outbound requests to external networks. In a perfect world, the idealistic software developer would frown upon such practices, following the purist notion that all backend API calls for data should happen on the local network. While I agree that software should be designed with this adage in mind, sometimes making outbound requests is inevitable. In this short article I’d like to share a tip I use to shave a few milliseconds off of outbound requests that can can improve your overall Apdex scores and keep your users happy.
A Long Running Service We Take For Granted
How many of you are familiar with these IP addresses: 18.104.22.168 and 22.214.171.124? I’m sure many of us have seen these a handful of times. These are the addresses for Google’s public DNS servers. These IPs are easy to remember, and if you need to enter DNS server addresses in a pinch, these usually are the quickest to come to mind . Whether or not we should use them as DNS servers is another topic entirely, but the fact remains that many do. I bring this up to illustrate a point, that many of us take the DNS service for granted. We plug DNS server IPs into our servers and workstations, and as long as we can lookup domain names, we’re good to go. This service is often overlooked on many server infrastructures, and may be adding unnecessary response times to your requests.
Looking at DNS Lookup Response Times
Let’s do a quick test. Let’s see how long it takes for our local workstation to do a lookup on Google’s Public DNS servers. For this test we’ll need the tool dig (domain information groper). Unfortunately for Windows users, dig does not come with the OS, and must be installed. If you use Windows, you can always use Cygwin to get access to dig, or if you want to install the native version, here are a few links to help you out:
https://samsclass.info/40/proj/digwin.htm (Windows 7)
http://www.blog.paranoidpenguin.net/2014/09/how-to-install-dig-on-a-windows-8-1-64-bit-system/ (Windows 8)
http://nil.uniza.sk/linux-howto/how-install-dig-dns-tool-windows-10 (Windows 10)
Most Unix and Linux distributions will have this installed by default, and I’ll be testing on Mac OS X which also has dig as part of the default installation.
Now onto the test. Pop open a terminal and run this command:
dig @126.96.36.199 jixee.me
This tells dig to use Google’s DNS server to lookup jixee.me.
You should see something like this:
; <<>> DiG 9.8.3-P1 <<>> @188.8.131.52 jixee.me ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12030 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;jixee.me. IN A ;; ANSWER SECTION: jixee.me. 293 IN A 184.108.40.206 ;; Query time: 87 msec ;; SERVER: 220.127.116.11#53(18.104.22.168) ;; WHEN: Sun Jan 3 17:58:10 2016 ;; MSG SIZE rcvd: 42
The important piece of information we want from this output is “Query time”. Now from the same terminal let’s just run dig to use the DNS server our workstation is configured with. Type:
You should see something similar to this:
; <<>> DiG 9.8.3-P1 <<>> jixee.me ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30328 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;jixee.me. IN A ;; ANSWER SECTION: jixee.me. 290 IN A 22.214.171.124 ;; Query time: 4 msec ;; SERVER: 192.168.2.1#53(192.168.2.1) ;; WHEN: Sun Jan 3 18:00:18 2016 ;; MSG SIZE rcvd: 42
Note the “Query time” in this lookup, and also the SERVER it’s using to resolve is on my local network. The query should be faster.
Speeding Up DNS Queries
Ok, by now you see where I’m going with this. To improve your application’s outbound request response times, make sure the servers hosting your application are performing faster DNS queries. You can accomplish this three ways:
- Point your servers at a DNS server on the same local network. You can choose to either find a server that your cloud provider hosts, or you can spin up your own. I opt for the latter, because you can control the amount of traffic on a DNS server you manage yourself, and often times, DNS servers of providers are busy machines. Depending on the amount of DNS queries your application makes, if you do this properly, you can get your avg DNS lookup response times between 1-5ms. This is significant when compared to the query time above of 87ms. Digital Ocean has a great community doc on how to create your own Caching (or Forwarding) Name Server here.
- The other method, which is easier to implement, but harder to quantify with tools like dig, and also harder to maintain, is to simply add the addresses to your server’s /etc/hosts file. The trick with this method is to make sure that your application’s DNS calls are actually using the entries in /etc/hosts. As a quick example, Node.js has a DNS module that has a couple ways you can resolve addresses: dns.lookup() or dns.resolve4(). The former will look at /etc/hosts before querying a DNS server, and the latter will only query a DNS server. If you’re using entries in /etc/hosts, it’s important to use dns.lookup(). As for maintenance, remembering to keep /etc/hosts up to date can sometimes be an afterthought, and it’s often easier to rely on the provider of the services you’re using to keep their DNS zones up-to-date. In addition, providers may change their IP addresses without you knowing, which could cause service interruptions if you rely on manually entering these IPs in /etc/hosts. If you like fewer things to remember, and less chance for issues, opt for method 1. It’s more work to setup, but less work in the long run.
- Make sure the servers hosting your application are using a local resolver cache. For Windows and Mac, this comes by default. For Linux/Unix, it’s not always installed by default, so you’ll have to install it manually where it doesn’t exist. The software you’ll want to install is NSCD (Name Service Cache Daemon). This will allow your application server to cache DNS queries so all future queries of the same domain names will be done locally. Keep in mind that your application will need to use DNS lookup methods that query the system first before querying the server, much like in the /etc/hosts method above. This method also adds a tad bit more maintenance, as you’ll need to make sure all of your application servers have a local resolver cache installed. Method 1 is still looking good to me.
So there you have it. Shaving 70-80ms off of a DNS query might not seem like a lot, but can make a big difference if your application makes several outbound requests. The total reduction in response times could add up to a snappier experience for your users. Most of us may never care about how long it takes to make a DNS query, but if you are developing an application that depends on external API calls, response times in DNS lookups can be the difference between a happy user and a frustrated user.