WAR on the Cloud, Part 3 I'm moving mirrors of my busy-ish website from my hand-crafted dedicated colo solution into the cloud to try to get geographically closer to my global user-base, reduce latency and improve perceived performance, save money, and hopefully make administration easier.
In part 2 of this series, I managed to get a minimal fairly "dumb" WAR file running in the Amazon AWS cloud and established that it wouldn't be hostile to some features which I rely upon to improve user experience, such as seeing the client's IP address.
I also found that it is possible to rack up minor charges even in the "free" tier when not doing anything exceptional, and my bill over a few weeks with AWS has now surged ahead to a massive 10 cents (except that AWS has "forgiven" the 3c bill from March), and that there is no way to explicitly cap a monthly bill.
Over the past fortnight or so I've moved one leg of my real website into AWS, and given the code and configuration a few days' tweaking to make it play nicely. It also seems that the only really uncontrollable bill would be from inbound bandwidth, so for example an infinite loop is only a problem if you let AWS bring up new instances indefinitely in response to CPU overload/utilisation.
This time I've also been able to investigate and try alternatives to AWS: less cloudy and buzzword-compliant but still more efficient in use of physical resources than my current dedicated boxes. Since my aim is to get mirrors geographically close to my (scattered) users to improve performance, and since my site consumes about 1TB per month, running something cheap from my bedroom (or any other single server) doesn't cut it!
The candidate alternatives for this round are:
- Rackspace (UK)
- Webvisions (SG)
- Google App Engine
Performance and bandwidth
My current servers are old or severely resource-constrained, and the solutions I tested seemed fast enough and indeed faster than some of my existing kit. The minimum requirement for my mirrors is roughly 512MB Java heap (though I can run with half that), 500MHz x86 CPU, and 1GB to 2GB of local working storage ("javax.servlet.context.tempdir") for cache.
Pointing users at a mirror geographically close to them should reduce latency (ie, response time) and may often be more important than CPU ooomph. I'd like lots of small cheap mirrors outside my main US and UK visitor areas.
Another issue is bandwidth: typical use of the site involves some low-bandwidth browsing through a catalogue, followed by the occasional download of a several-MB multimedia file. So the average bandwidth requirements are modest, but I'd like to be able to "burst" to many Mbps so that users with fast connections can download in a few seconds. With one of my current hosts I have a capped "95th percentile" bandwidth agreement which works well for this and reflects real wholesale costs, but all the solutions that I investigated this time around were either pay-by-the-byte without any cost cap, or fixed-maximum-bandwidth with a fixed cost, neither being optimal for reasons of my risk or user experience.
I want an individual cloud mirror to go offline if well over bandwidth (or CPU) budget since in most cases other mirrors – especially those on cost-capped hosting arrangements – can take up the slack, at least until they're full. I already limit peak and monthly-average data outflow from each mirror, and attempt to reduce hotlinking, etc, but an error on my part, or a DoS problem from someone else's DNS error, or broken links, or even a gone-wild search-engine bot (I've seen all of these happen), remain a threat – and this is discounting malicious doings. Google's App Server seems to be capable of automatically pulling the plug in this sort of circumstance, and providers with capped-cost plans are shouldering the risk themselves, so why not some support from the others too?
(I'm not expecting any cloud provider to indefinitely protect a site that's deliberately brought a storm of contumely, ie the brown stuff, on itself, such as by taunting 1337 h4x0rz. But dropping any DNS entry, server interface, and possibly even blackholing routing to a drowning site automatically could save a lot of tears and $$$s all round.)
Note that the only non-US/UK "cloudy" (and English-friendly) solution that I was able to locate was by gently twisting the arm of my existing provider, Webvisions. Other suggestions would be very welcome in comments.
Ease of set-up and management
To run a mirror I need a fairly bare-bones *nix system with JDK1.6, a newish Tomcat (4 or 6) and a minimal attack surface (no spurious services exposed), and /etc/resolv.conf set up for DNS resolution. Then I can drop my WAR file into Tomcat and off we go. Alternatively, the AWS-like solution is to tweak Java settings, upload my WAR file into their container, and again we have traction.
Google App Engine
Unfortunately the Google App Engine fell at the first hurdle as it seems that GAE would choke on my standard WAR file that fires off lots of background threads and that supports long-running operations. The GAE experience seems too different to the alternatives to be worth the development and maintenance effort for now.