Apache is slower on other computers on local area network than on localhost

I have few computers connected into network. There's a server inside that network which hosts WAMP (Windows + Apache + PHP + MySQL). There is Windows 7 x32 Pro installed on it. I can ping that server from my wireless connected server, all pings are 1ms. What is interesting, when I browse my web application on server itself, it loads in the blink of eye. I can surf subpages like they were images which I’m just switching.

However on the other computers it works slower. It’s not tragic, but noticeably slower. In some cases browser shows “Waiting on…” which takes one or two seconds, and this is the most painful.

I figured out that it is much faster to use application on server while I’m connected via remote desktop, than on any other computer. That would be awesome if I could get the same effect on them.

When I look into developer console in chrome I can see that: the DOMContentLoaded is like 400-600ms on server, and 1400ms on every other computer.

What can I do in that situation?


Solution 1:

Make sure HostnameLookups is set to Off in Apache.

You say the server is running Apache via a WAMP (Windows equivalent of LAMP) setup, correct? Well if that is the case open up httpd.conf or apache2.conf (all depends on how it was installed on your setup; both files are basically the same) and look for a configuration line with HostnameLookups in it. By default HostnameLookups is set to Off as explained in the comment that should be right above the HostnameLookups setting in that file; bold emphasis is mine:

HostnameLookups: Log the names of clients or just their IP addresses e.g., www.apache.org (on) or 204.62.129.132 (off). The default is off because it'd be overall better for the net if people had to knowingly turn this feature on, since enabling it means that each client request will result in AT LEAST one lookup request to the nameserver.

And the official Apache documentation goes into deeper detail as well; again bold emphasis is mine:

The default is Off in order to save the network traffic for those sites that don't truly need the reverse lookups done. It is also better for the end users because they don't have to suffer the extra latency that a lookup entails. Heavily loaded sites should leave this directive Off, since DNS lookups can take considerable amounts of time.

Don’t use hostnames for Allow from/Deny from directives.

Also, do you have any directories or directives that use Apache Basic Auth? Which is the simply password protection one can set in Apache? I recall in some cases there were slowdowns related to hostname lookups connected to Allow from fields such as an Allow from localhost. Commenting out Allow from localhost or setting that to Allow from 127.0.0.1 ::1 and then restarting Apache would clear that up.

As explained in the official Apache documentation even with HostnameLookups set to Off using full hostnames in Allow from/Deny from directives will trigger a whole chain of DNS lookups that can slow down access; bold emphasis is mine:

Hosts whose names match, or end in, this string are allowed access. Only complete components are matched, so the above example will match foo.apache.org but it will not match fooapache.org. This configuration will cause Apache to perform a double reverse DNS lookup on the client IP address, regardless of the setting of the HostnameLookups directive. It will do a reverse DNS lookup on the IP address to find the associated hostname, and then do a forward lookup on the hostname to assure that it matches the original IP address. Only if the forward and reverse DNS are consistent and the hostname matches will access be allowed.

This blog post also explains it nicely if you care to read more details on how Allow from/Deny from entries that have a hostname—instead of a raw IP address—can slow down Apache access because of multiple DNS lookups:

However, I recently came across a situation where we inadvertently were doing the equivalent without explicitly enabling HostnameLookups. How? By limiting access based on the remote hostname! Read the documentation on the Allow directive, under the section "A (partial) domain-name":

This configuration will cause Apache to perform a double reverse DNS lookup on the client IP address, regardless of the setting of the HostnameLookups directive. It will do a reverse DNS lookup on the IP address to find the associated hostname, and then do a forward lookup on the hostname to assure that it matches the original IP address. Only if the forward and reverse DNS are consistent and the hostname matches will access be allowed. This makes perfect sense, but it is a pretty big likely unexpected side effect to using something like:

Allow from .example.com

In our case it was an even less obvious case that didn't make us think of hostnames at all:

Allow from localhost

Here localhost was written, perhaps to save some effort or maybe increase clarity vs. writing out 127.0.0.1 (IPv4) and ::1 (IPv6). Mentally it's so easy to view "localhost" is a direct alias for 127.0.0.1 and ::1 that we can forget that the name "localhost" is just a convention, and requires a lookup like any other name. Those familiar with the MySQL database may know that it actually assigns special confusing meaning to the word "localhost" to make a UNIX socket connection instead of a TCP connection to 127.0.0.1 or whatever "localhost" is defined as on the system!

You may also be thinking that looking up 127.0.0.1 is fast because that is usually mapped to "localhost" in /etc/hosts. True, but every other visitor who is not in /etc/hosts gets the slow DNS PTR lookup instead! And depending on the operating system, you may see "ip6-localhost" or "ip6-loopback" (Debian 7, Ubuntu 12.04), "localhost6" (RHEL 5/6, Fedora 19) in /etc/hosts, or something else. So it's important to spell out the addresses:

Allow from 127.0.0.1
Allow from ::1

Doing so immediately stops the implicit HostnameLookups behavior and speeds up the website. In this case it wasn't a problem, since it was for a private, internal website that couldn't be visited at all by anyone not first allowed through a firewall, so traffic levels were relatively low. That access control is part of why localhost needed to be allowed in the first place. But it would have been very bad on a public production system due to the slowdown in serving traffic.