Although it is often possible to improve the responsiveness of your servers and services you should make sure you regularly test your server under load to ensure it continues to function as you expect.
In most of the recipes we have posted we’ve listed suggested values for settings such as
max_connections. These are just guidelines that work well on reasonably powered servers.
You might find that because a single connection requires, for example, 10Mb of RAM, you can only sustain 500 of these at the same time before your system is out of resources.
You need to find this limit for yourself, and adjust accordingly.
Mitigating Service Failures
Even if things are working well it is helpful to install some kind of process monitoring upon your servers.
These will catch the case when your servers exit unexpectedly and quickly restart them.
There are many tools you can consider using such as
runit, each suited to a different kind of control:
- Restarting services when they fail.
- Restarting services which have exited.
Whenever you attempt to make a tweak to your systems performance you need to know what result you’ve achieved, if any.
The best way to do that is to use a tool to test your servers performance, or throughput, and run that both before and after making any particular change.
There are several benchmarking applications and tools out there, and this small page contains a list of the ones you’re most likely to need to use.
Webserver benchmarking largely consists of firing off a few thousand requests at a server, and reporting on the min/max/average response time.
Obviously a server “loses points” if some of the response are errors, rather than valid results, but generally the testing is a matter of juggling the number of total requests, or concurrent requests, until you reach a point where the server starts to take too long to respond, or fails completely.
One of the most popular tools for benchmarking for many years was
ab, the Apache benchmark tool. This is looking a little dated now, but still works well.
If you’re running Apache you probably have this installed already, which explains its popularity. Give it a URL, a number of requests, and a concurrency level and it will issue a small report:
Here we’re going to look at the results of applying some of the nginx-proxying updates to a standard server.
The testing we’re carrying out is of
nginx as a reverse-proxy in front of a slow HTTP-server:
- Internet > nginx > Application server
Posting benchmarks is usually a mistake, because the only thing you care about is the increase in speed in yourserver, or application. Benchmarks tend to be on unrelated systems, with different hardware and unrealistic traffic patterns.
The only fair benchmark I can think of posting is of a reverse-proxy because everything else stays the same. The actual performance of the back-end is largely irrelevent, we’re just testing the overhead, or speedup, introduced by the middle-layer.
But note that even this benchmark isn’t fair or realistic, because it only covers the case of hitting a single static URL – It isn’t representative of a real website.
The initial testing is literally with Apache proxying through to the application, with zero caching, and zero tweaks.
The nginx configuration file is available for download.
The testing uses siege to fire off 50 concurrent connections for 2 minutes, via this command:
siege -c 50 -t120s http://localhost:8888/index.html
The results were:
Transactions: 10477 hits Availability: 100.00 % Transaction rate: 87.31 trans/sec
We now configure
nginx to cache the results of all static pages, which as luck would have it would be all of our site – as this is not a dynamic application.
The updated configuration file is available for download.
We’d expect a significant increase in performance with this caching, because we only expect to hit the back-end once – the rest of the requests will be served from the cache.
As expected our throughput increased, because only a single request was actually processed by the back-end. The rest of the responses came from the cache:
Transactions: 11882 hits Availability: 100.00 % Transaction rate: 99.31 trans/sec
Jumped from 87 transactions per second to 99. Not a huge gain, but certainly a measurable one.
Updating Buffer Sizes
Finally we tweak the buffer sizes. The average page-response in our simple HTTP-server is 50k, but we’re only hitting the front-page which is a little smaller.
Updating the buffer-sizes in our configuration file leads to the following results:
Transactions: 12930 hits Availability: 100.00 % Transaction rate: 107.75 trans/sec
This took us from our original result of 87 transactions per second to just over a hundred.
If you’re serving static files then using
nginx as a caching reverse-proxy will give you a performance boost.
In the real-world most sites are not 100% static, but you can apply this idea to serving
/images, and similar paths from an
nginx cache, proxying the dynamic requests to another server.