So far so good, but this is just the beginning. To be able to make your website serve as many requests as possible, it’s important to make a few basic adjustments to the default installation of Apache and MySQL.
When we talk about web performance at a grand scale, we usually mean having a fast response to web requests, making your website load as fast as possible.
Now, that’s easier said than done, but mostly because there are many angles of attack when we talk about the speed in which a page loads. For instance, sometimes, the server is a beast of a machine but the software is not well configured for the occasion.
Sometimes the server and software are just fine but you have a few tables in your database that need indexing. Or your PHP script could use a little more optimization. So we find ourselves having multiple scenarios that call for different solutions.
There are entire books written on this subject but as a rule of thumb, performance improvements are an ongoing process where iteration, testing and measurements are the key to a fast website.
Let’s get to it
Here we present you with some practical tweaks to make your basic installation handle a little bit more. And although there are a lot more parameters than those exposed here, this is a great starting point.
– Unused modules:
Apache processes are memory hogs, it’s common to see them using over a hundred megabytes of ram. Picture a server of 1 GB of ram, 5 people browsing the site and you can see how things could quickly turn for the worse. Disabling unused modules ensures that every process started uses only what it needs.
To disable a module on Apache 2 you just do the following:
And then make sure you restart Apache
– Keepalive (persistent connections):
This option tells Apache to keep a connection for a given client so it doesn’t have to spawn a new process all the time, which has a considerable overhead when we are talking about multiple connections from several clients. It’s a good idea to enable this option (set it to On) but only if we get the KeepAliveTimeOut parameter down, since a big number could clog up the server with unnecessary processes.
Since a web page usually does not take more than 3 seconds (unless there is something wrong), this parameter should be in the 3-5 range.
Also, if we know our website has a lot of page loads (for instance, because it’s a web application), it’s also a good idea to have a big number of MaxKeepAliveRequests.
Lowering the general timeout to something more reasonable always make sure no Apache processes are lying around for too long. Be careful not to lower it too much though. A value of 10-15 is a good starting value.
– Name server resolution:
Apache logs are a powerful feature that can later be used for a variety of purposes, from security auditing to traffic processing. It’s much more readable to humans to have a hostname than a IP address and while one hit to a name server might not be that much, a site with a lot of traffic adds up in requests.
If you don’t need this at all, it’s better to have it Off.
– .htaccess file lookup
If you have a virtual host that’s not using .htaccess files, set AllowOverride parameter to None so Apache doesn’t look check each directory for .htaccess.
– Amount of processes:
This is mostly dependent on the memory available and cores. The basic settings won’t give you much simultaneous connections but it’s a good idea to play with them until you find the right balance.
One thing is for certain, do not let that memory ran out since it will swap to disk and that’s going to slow down the server considerably. And if you have disabled the swap memory, the kernel will start to kill the processes (if we are lucky) or grind the server to a halt.
Also, it’s key to understand how many visits our site will have, at least a ball park figure. With that in mind, we can anticipate and set the numbers accordingly. Fortunately, thanks to City Cloud, it’s easy to scale up when needed.
To give you a point of reference, for a server with 2 cores and 1 GB of RAM, this could be useful (assuming the multi-process version of Apache2):
These parameters are optimistic. They assume you won’t have more than 50 clients connected at the same time. Of course, this is usually tailored to one’s needs. To give you an idea, 50 simultaneous user at a peak may represent a site with 2000-3000 daily visits. Which is a small site but nothing to scoff at.
This is one of the greatest optimizations for sites that have a lot of traffic and generally read from the database. Caching means that common queries are retrieved from the cache, which is orders of magnitude faster than doing the full query.
Caching takes a toll on memory, so care must be taken that enough memory is available to our MySQL server process. Of particular interest we have the following parameters, given a server with 1 GB of RAM as reference:
query_cache_type = 1
query_cache_size = 32M
key_buffer_size = 64M
thread_cache_size = 4
max_connections = 150
– Separate the database:
This is not a setting but a common practice. If you start with a small server, chances are you have the web and database server in the same machine. Once traffic starts to get higher, things tends to get messy since Apache and MySQL are fighting for resources.
Fortunately, the process of moving a database out of the main server is not a complicated one (and a great idea for an upcoming blog post!). Of course, if you happen to have a site that grows constantly, you will possibly enter the realm of replication, automatic failover and other techniques that are used when you have a database spanning multiple servers.
– No substitute for a well designed database
Last but not least, if your database has a non-optimal structure, it doesn’t matter how much you scale, you will always have bottlenecks that have nothing to do with your server settings. Making sure your database has a good structure is just as important as having the right infrastructure.
Remember that this is just one way to optimize (and a subset of tweaks). You also have other options, such as choosing another webserver (nginx for instance), scaling vertically or horizontally, optimizing your database and code.
Also, what we’ve exposed here lies around basic optimization and it’s definitely not the ideal case (where, as we’ve mentioned, the database has its own hardware, etc) but it will get you by while you concentrate on your site.
For now, this is a great way to start pumping more requests per second. Soon enough we’ll publish articles on other ways to get more juice out of virtual servers. This is just the beginning on an exciting journey towards greater efficiency.