There are numerous methods and opinions on how to cope with each of these scenarios and this post will by no means even come close to scratching the surface on either of them. I am however going to outline a few points that I think are important to remember and implement on sites with a reasonable amount of traffic.
I read a serverfault post the other day about how to plan for higher traffic and the number of requests that you need to be prepared for. They suggested the following calculation assuming your site is 10 pages deep, or you average 10 clicks per visit.
((60 seconds in a minute) x (60 minutes in an hour) x (the number of requests your server can handle a second)) / (average visitor clicks)
Lets look at an average blog and untuned apache and mysql instance running on a small 512mb VPS solution. On an untuned instance, you might get 3 apache requests per second for an average database backed site. A great way to test your site and to benchmark and improve performance in general is to use the apache ab tool. This is bundled with apache when you install lamp on most servers and also comes installed on mac’s with the default apache version. An example ab request is below.
ab -n 100 -c 10 http://yahoo.com/
As a note ab simulates requests to your server. It does not actually download the entire page including images and js. To simulate actual load, you will need to use another solution. It does do at “GET /” though, so it will actually request your html.
Traviss-MacBook-Pro:~ Trav$ ab -n 100 -c 10 http://yahoo.com/ This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking yahoo.com (be patient).....done Server Software: YTS/1.20.13 Server Hostname: yahoo.com Server Port: 80 Document Path: / Document Length: 211 bytes Concurrency Level: 10 Time taken for tests: 0.806 seconds Complete requests: 100 Failed requests: 0 Write errors: 0 Non-2xx responses: 100 Total transferred: 43900 bytes HTML transferred: 21100 bytes Requests per second: 124.00 [#/sec] (mean) Time per request: 80.648 [ms] (mean) Time per request: 8.065 [ms] (mean, across all concurrent requests) Transfer rate: 53.16 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 29 36 7.6 31 48 Processing: 29 41 26.2 35 289 Waiting: 29 38 7.7 34 55 Total: 58 77 28.7 66 318 Percentage of the requests served within a certain time (ms) 50% 66 66% 89 75% 91 80% 91 90% 93 95% 94 98% 100 99% 318 100% 318 (longest request)
Back to our math problem. If your site supports 3 requests per second, plugging this into our equation yields 1080 unique visitors per hour or around 25,000 visitors per day on a stock apache instance. For a slashdotting or DDoS attack though, this may not be sufficient when you are receiving hundreds if not thousands of requests per second. We need some stop gap measures.
I have 3 suggestions below that I use on higher volume sites and web services to prevent and cope with high traffic.
Varnish is the quickest way to prepare for a high amount of traffic in the least amount of time. Varnish cache is a web application accelerator. It can be installed on the same server you have your web server running on and it sits in front of your webserver and caches those pages. It is great for content heavy sites where you don’t need to spin up a new apache process for every request. Varnish Provides a great overview and instructions on how to install this here: https://www.varnish-cache.org/about
Nginx + Varnish Cache
If you have more than a few minutes to prepare your servers, you may look at changing web servers away from apache. A new, high performance web server that has been gaining popularity recently is nginx. It too, like varnish is a reverse-proxy. Putting in inline with varnish that yield some really great results and throughput for static and dynamic sites alike.
Digital Ocean provides a great tutorial on installing varnish inline with nginx: https://www.digitalocean.com/community/articles/how-to-install-wordpress-nginx-php-and-varnish-on-ubuntu-12-04
Stay tuned for a video as well on this.
If you are still seeing issues, the absolutely last thing I would recommend is to block ips. See the below .htaccess file. Just include the ip’s you want to block in the blacklist.conf file. Note that to include files, they should be .conf format.
order Deny,Allow include conf/blocklist.conf Allow from all
Ideally here, you don’t want to manage this. You want your blocklist to be updated dynamically. This could be done if you are logging visitors with header information. If this data is read in a database, its as simple as creating a cron that runs every minute to look at the database and rebuild the blocklist.conf file with IP’s that have exceeded your limit for visits in the amount of time you determined. This needs a tutorial as well, and I will do that in a later post.