10
Mar 10

Performance tuning a server in less than three minutes while being slashdotted

So you wrote a blog post about something that seemed fairly innocuous, but for whatever reason, it caught the attention of one of the major sites and now your server load is at 110 and climbing, the ssh command line session is taking thirty seconds to respond to anything at all, and given that your post is on the front page of slashdot at primetime, this doesn’t look like it’s a temporary blip. What do you do?

Burning computer

Okay, first things first. You don’t have time to do a proper fine-tuning session. You need a quick & dirty tuneup here. Proper fine tuning you leave till after the traffic spike, and you can then come back at it with a plan and decent tools like siege and so on – but this is the “fix it in three minutes” version. So if you see stuff here that looks crude to you, despair not, everything looks crude when you’re trying to do it in that kind of timeframe.

First, you have to be able to actually use the server command line. The load’s at 110 – that’s not coming down anytime soon and until it does you can’t do the rest of the work you need to since it takes so much time for even a shell to respond. The load is being caused by Apache and MySQL taking on more work than the server can handle, causing the server to swap excessively; and you’ve got to dump that work or shut off the incoming new work to recover. You can try sudo killall -9 apache2 if you can get an open ssh terminal in to do the job (and it’s the first thing you should try), but the odds are that that server has to be reset. Whether that means a phone call to the data centre, or a walk down the hall to the server room, or just clicking a button in a web interface, that’s the first thing to do. Don’t hold off, because unless everyone stops reading your page right now, that load’s not coming down.

Once the box has rebooted (and I mean immediately – sit there watching ping until it comes back), ssh in and shut down apache. MySQL is okay for now, but the work is coming from Apache, so that has to get shut down until everything’s ready to go again. You’re going to lose a few minutes of service, yes, but that’s recoverable from for a blog (and if this is for something more serious than a blog, you’re going to be in trouble for not properly spec’ing the hardware to begin with anyway, so limit the damage now and take your licks later).

At this point — whether you’ve just logged in or whether you managed to run killall successfully —  if it’s a debian server you should run sudo /etc/init.d/apache2 stop (did I mention I love debian for having scripts like that? No man-paging apachectl, just an easy to remember standard interface for every service on the box. Wonderful). It’ll tidy up from killall, or it’ll shut down apache cleanly, depending on how you got here.

I’m going to use my server as the example here, by the way, since it’s what got burned last night and it’s what prompted me to write this refresher — it’s been two or three years since I last had to maintain a server that was near its capacity, the experience was a bit of a flashback 🙂 So, some background on my server – I moved my blog from wordpress.com to here, on a Hetzner server. It’s their entry-level dedicated server offering 2Gb of RAM, a 64-bit Athlon, 160Gb of hard drive in a hardware RAID-1 array and a 1Gbit NIC) — all running Debian Lenny (and no, I’ve no relationship with Hetzner, they were just the cheapest of the places various friends recommended). WordPress is up to date on my server (2.9.2 at the time of writing), as is the Lenny install — if you don’t have the latest security fixes and such in place, or your WordPress is outdated, then that’s probably adding to your problem, but for a quick fix like this, that’s too big a job. Get through the traffic spike and deal with it later.

And yes, that server spec is overkill for my needs really – but I had a bunch of side projects like RangeClerk (don’t bother, not much is up yet) and the blog for Herself Indoors and her book and some other things I wanted to run as well that would be using wierd php and python modules and libraries and the like; and I just hate cpanel and not being able to install anything I wanted. Plus, it was cheap 😀

Right, back to it.

The first thing we need to do is to sort out MySQL’s configuration. Open up the my.cnf file, whereever you’ve put it (it’ll be /etc/mysql/my.cnf for a stock Debian install). We need to tweak just a few settings. First off, key_buffer. This is probably the most critical variable here because by default all the tables will be MyISAM tables (if they’re not, then this isn’t so critical). It’s set to about 16Mb by default; we’re going to turn that up quite a bit. On a dedicated database box, this would be set very high – anything up to 50% of the total available memory. In this case, with a full stack on the one box, we set it a bit lower since Apache’s going to want a lot of RAM too – 256Mb will do for a starting value.

Next we’re going to disable the InnoDB engine completely to cut down on MySQL’s footprint. Again, WordPress by default isn’t using it. Just ensure skip-innodb is either uncommented or inserted into my.cnf.

Lastly, we’re going to enable the query cache. The thing is, MySQL’s query cache is a fairly blunt instrument. If a query is precisely the same the second time it comes in, it’ll hit the cache – but any change at all, no matter how small, and it misses the cache. So it’s not as enormously useful as you’d first imagine. However, it does help, so we’ll increase its size modestly (48Mb of RAM is sufficient here). So our changes to my.cnf look like so:

[cc lang=”ini”]
key_buffer = 256M
query_cache_limit = 16M
query_cache_size = 48M
skip-innodb[/cc]

Once those changes are made, sudo /etc/init.d/mysql restart will get the MySQL server up and running with the new setup.  Once that’s done, let’s look to the next level in the stack – Apache. Under debian the config files are arranged differently than normal; the configuration changes we’ll make will be in /etc/apache2/apache2.conf but in other installations they would be in httpd.conf or elsewhere.

The default Apache install uses the prefork MPM setup – one thread per process. It’s older, slower, less efficient, but less buggy than the worker MPM which isn’t threadsafe. So find the prefork MPM config settings in apache2.conf. They should look like this in a default install:

[cc escaped=”true” lang=”apache”]
<IfModule mpm_prefork_module>
StartServers          5
MinSpareServers       5
MaxSpareServers      10
MaxClients          150
MaxRequestsPerChild   0
</IfModule>[/cc]

We’re going to cut down a lot on how much work Apache takes on at once here. Yes, some users will have to wait a few seconds to see your page – but right now, with the load at 110 and climbing, they could wait until their browser timed out and they’d never see anything. So we reduce slightly the number of servers that Apache will farm off to handle requests at any one time from 5 to 4; we’ll increase the number of spare servers it’ll keep around to hand off requests to (we want to reduce the overhead of starting and stopping those processes) from 10 to 12. We’ll set an upper limit on how many we can have though, and we’ll keep it to just under 100. This works on my system, which is an entry-level system; you might get away with more, but for now use these settings and it’ll get you up and running and you can increase a bit and check again as you go (and this guide really isn’t aimed at big sites anyway, just small ones like mine which were caught on the hop). We’re also going to ensure no apache process takes on too much at once by creating a limit of how many requests any process can take on – we’ll keep it low for now (3), but it can be increased later. So our changed config settings now look like this:

[cc escaped=”true” lang=”apache”]<IfModule mpm_prefork_module>
StartServers          4
MinSpareServers       4
MaxSpareServers       12
ServerLimit           96
MaxClients            96
MaxRequestsPerChild   3
</IfModule>
[/cc]

Okay. At this stage, you have two options. The first is to start Apache up again and get back to work. Odds are, this will hold up pretty well – but you want to keep a window open with htop running in the background to keep an eye on things (and mainly you’re watching the swap space usage and the load. The former’s critical, the latter indicative that a problem’s arising – if either go sideways, kill apache and edit apache2.conf setting even lower values for ServerLimit, MaxClients and MaxRequestsPerChild before restarting apache). If that’s your preferred option, skip to the end of this post.

However, if you want to take that extra step, we could install memcached quickly here. It’s a very effective load reducer and under debian, it’s far easier than you’d expect:

[cc lang=”bash”]sudo aptitude install build-essential php5-devel php-pear memcached[/cc]

And let that haul in whatever other libraries it needs, then:

[cc lang=”bash”]pecl install memcached[/cc]

And once that’s done, edit the php.ini file (in Debian, that’ll be /etc/php5/apache2/php.ini ) and insert this (anywhere in the file will do, but the extensions section is the tidiest):

[cc lang=”ini”]extension=memcache.so[/cc]

That should be memcached installed and running in a default configuration (we can finetune later). We now need to drop in the backend that WordPress uses to take advantage of memcached. Download object-cache.php and copy it into the wp-content directory of your website and change the permissions and ownership of the file:

[cc lang=”bash”]cd [insert your www/wp-content directory here]
sudo wget http://plugins.trac.wordpress.org/export/215933/memcached/trunk/object-cache.php
sudo chown www-data.www-data object-cache.php
sudo chmod 644 object-cache.php[/cc]

And that’s it done. Quick, dirty, and everything at default, but that’s a three-minute setup for you (well, maybe five if you do the memcached setup as well, and I am assuming you have a fast net connection for the aptitude step, but still).

Now, restart apache and everything should fire up with memcached caching a lot of requests and keeping the server load to a managable level.

[cc lang=”bash”]sudo /etc/init.d/apache2 force-reload
sudo /etc/init.d/apache2 restart[/cc]

And once that traffic spike is past… take the time to tune it properly!


09
Mar 10

Silently banned from Reddit…

Reddit Alien - Screw You Buddy

For almost two years now I’ve been reading Reddit and posting material there, mostly in Programming but in other subreddits too. I’ve built up positive karma points there, I’ve never broken the site rules, and I’ve been a fairly regular reader there. A few days ago I posted a review on the new headphones I bought to the audio and headphones subreddits, and there wasn’t a single blip on them – no comments, no votes, nothing. That’s rather rare for reddit, usually there’s something. And then I noticed in the statistics on the blog that I was seeing no referrals from there at all either, which is very odd. I looked at the site and sure enough, there are the posts, so what’s happening?

It’s at this point that I find that noone else can see the posts at all. And I log into my user page from a test browser which isn’t logged into my account and find that my userpage on reddit is giving a 404 error.

Reddit User Page 404 error

So my first reaction is “what the…?”, and I send a message to the admins of the site asking what’s broken. Twice, in fact.

I’m still waiting to hear back, five days later.

In the meantime, however, I find that this is apparently standard practice for Reddit — if you’re judged to be at fault, you’re just silently dropped. They call it the zero point ban and as ways of dealing with your userbase go, it’s probably one of the more cowardly I’ve encountered. Here’s how it goes:

  • Firstly, you don’t document all the rules. Sure, there are basic site rules and FAQs and “Redditiquette”, but you don’t put everything in there.
  • Then, you let anyone at all report anyone else, without having to make a case beyond the initial accusation.
  • Then, you don’t let anyone know that they’ve been reported for something.
  • You make sure that users past records aren’t taken into account – so that even when your karma is good, it doesn’t matter.
  • Then you don’t let anyone know they’re being judged.
  • Then you don’t let anyone know if they’re found wanting.
  • Then you don’t tell them they’re being banned.

So, I have to go digging back through the spam reporting sub-reddit (which I didn’t even know existed this time a week ago) to find I had been accused at all, and since your username isn’t actually instantly visible (it’s in the link, so you have to run your mouse over it while watching the status bar), that’s not a trivial task when someone reports someone else every few minutes:

reddit - Reported For Spamming

Once I found that, I thought “Well, okay, at least I can argue my case here so”. Except, no, any comment you make here doesn’t come up because you’re banned by this point. Maybe if you’d been here earlier (as in 19 hours ago when I first found this) you could have argued your case – but because you didn’t get told you were up for review (you weren’t even downvoted by the person who reported you), you didn’t know you were being judged and now you’re right out of luck. So you can comment, and the system even notes that you have commented, but noone else can see your comment.

I might not even be all that annoyed, to be honest, but when you find that your accuser has been less active on the site than you, that he’s built up less karma than you have, that he’s never contributed anything original to the site and has only posted 26 links when you’ve posted over 260 (including some which were in the reddit.com top ten and which have tens to hundreds of thousands of hits) — well, that rankles. It’s just plain wrong.

Reddit karma pointsReddit accuser karma points

Granted, you couldn’t arrange things so that you must have more karma points than someone to accuse them of something, that just wouldn’t be fair either, but surely it’s only right to let people know they’ve been accused of something, right?

As a way of interacting with your users go, this is not just sub-par, it’s downright sneaky. And the cynic in me thinks that the fact that this requires a minimum amount of work by the admins, and that it still generates site traffic and ad clicks, are motives for either not fixing this, or designing it this way from the get-go, and that’s even more sneaky.

So now what?

Well, in the greatest traditions of websites everywhere, IYDLIGTFO. Between Digg, StumbleUpon, Mixx, Propellor, Diigo, HackerNews, DZone, Buzz and others, it’s not like there isn’t any competition or alternatives aplenty. And if this is how Reddit treats its users, it’s not someplace to hang out anymore.

Censored Reddit Alien


09
Mar 10

Suura over coffee

Filmed before Mobile World Congress:

[stextbox id=”custom” color=”000000″ bcolor=”0101fd” bgcolor=”e1e1fd”]Suura.com have developed patent-pending technology to silently authenticate 3G subscribers onto existing WiFi networks, without modification to those networks, creating the opportunity for 3G data subscribers to roam, without intervention, onto more cost efficient WiFi networks. Suura also meters the use, so the WiFi provider can be compensated for the offload.

Suura brings the promise of low-cost WiFi access through public hotspots. The system is targeted towards users that wish to surf the Web or make VoIP calls while they are roaming. Suura has the ability to seamless authenticate mobile devices through WiFi hotsposts using a single click mechanism and works on all the major mobile platforms.

Contact john.whelan@tcd.ie for more information or call +353-1-896-3269[/stextbox]