Sunday, April 19, 2009

Tips on Using Amazon CloudFront

If you are serving a lot of content with an audience that is spread out over the globe, then most likely you are in need of putting your content on a CDN (Content Delivery Network).  There are a host of options for you such as LimeLight, BrightCove and Akamai to name a few, but I have found that Amazon offers much of the same functionality at a better price.  Moving your static content to Amazon's CloudFront can really reduce the load on your servers and certainly enables you to serve your content from a place that is closer to the request.  The best thing about it is that it is very very simple to do.  There are some pieces of information that can really save you alot of time and energy if you are converting your site to serve content from CloudFront.  Here are some things that were important to me and that I had to address when moving our site:
  1. Speed
    • Faster delivery of all content from edge locations close to the request
    • Faster load time of a page in the browser
  2. Ability to serve content over HTTP and HTTPS
  3. Simple, straight-forward development
Speed
Amazon CloudFront allows you to manage the content in your S3 buckets and enable them for delivery from edge locations all over the world.  To enable a bucket for CloudFront, it is a simple API call to create a Distribution.  Once your Distribution is provisioned, which usually takes less than 15 seconds in my experience, you will be given a Distribution url which will look something like: http://abcd1234.cloudfront.net .  This Distribution URL can be simply though of as another URL to that bucket in S3.  For instance, if you have a bucket in S3 named "mys3bucket" and you create a Distribution for that bucket, which returned http://abcd1234.cloudfront.net, then you could reference that bucket as http://s3.amazonaws.com/mys3bucket/ or as http://abcd1234.cloudfront.net .  The only difference between the two is that the CloudFront URL will be served from the location closest to the request and the content from that distribution can be served at 1,000 Megabits per second and even more if needed and requested.  For the easy creation of your S3 Buckets and CloudFront distributions, I suggest using S3Fox for Firefox.  With a simple right click on your bucket through S3Fox, you can create a new Distribuion in seconds.
Beyond just offering the serving of your content from an edge location at high throughput, CloudFront distributions have another advantage that can speedup the loading of your sites pages.  Using a single Distribution, you can assign up to 10 CNAMEs to it.  This can really make a large difference when serving content for a page.  Most browsers block and only allow 2-4 parallel connections to a single host when loading content.  Creating 10 CNAME entries all pointing to the same distribution allows the browser to make 10 times the parallel connections it could using a single entry.  I would suggest Steve Souders book High Performance Web Sites: Essential Knowledge for Front-End Engineers for more tips on this.

HTTP and HTTPS Delivery
One of the drawbacks to CloudFront is that it does not support HTTPS delivery of the content.  However, there is some good news here because S3 does support HTTPS.  Because the content that you need to deliver over CloudFront sits in an S3 bucket, then you can also deliver that same content over HTTPS but you cannot take advantage of the edge locations.  This is especially useful when you need to serve a secure site that has a bunch of images that you are already serving from CloudFront.  If you try to serve those images over HTTPS, your users will get a security warning or no image at all because the browser will block it.  So, when you need to serve those secure pages, simply switch your delivery URL to the S3 location instead.  A word of advice here is to create your S3 bucket without using any '.'s.  I know that this really messes with you if you want your URL to look like it is coming from your servers, but it will allow you to serve secure content from S3.  The S3 bucket is served over HTTPS using a wildcarded certificate.  This allows Amazon to serve your content using any prefix as long as it does not have any extra dots ('.').  If your bucket name is 'mys3bucket', then you can create a CNAME record that points 'mys3bucket' to mys3bucket.s3.amazonaws.com.  Because the wildcarded SSL certificate is to *.s3.amazonaws.com, then you can serve your content from https://mys3bucket.s3.amazonaws.com.  While this isn't the perfect solution, it is really nice for serving the same bucket content over HTTP or HTTPS.


Simple, Straight-Forward Development
I am not sure that building scalable applications is ever simple, but I am always looking for ways to make it extremely repeatative and simple for myself and other developers. Because we are using Java for most of our applications, the easiest way for me to do that was through a tag library.  I included all of the logic for switching between the different CNAMES for CloudFront delivery and logic for detecting a secure connection and need to switch to straight S3 delivery right in the tag.  There were some interesting details that were necessary to take full advantage of CloudFront.  One was coming up with a hash scheme for a URL so that it could be cached in the browser and distributing the calls across the CNAMEs evenly.  The second was to make sure that the tag was written so that it was at the request level instead of the page level.  This helped ensure that even an included JSP would not cause a narrowing of the number of CNAMEs that I could use.  This is the method in the tag that does most of the work
protected String getCDNUrl() {
   String result = null;
   if (((PageContext) getJspContext()).getRequest().isSecure()) { 
      result = getCDNSecureUrl();
   } else {
      result = getCDNUrls().get((1 <= getCDNCount()) ? Math.abs(getFile().hashCode()) % getCDNCount() : 0);
   }
   return result;
}
CloudFront has proven to be very useful to me.  I hope with a few of these tips that you can improve the performance of your site.  Please share your experience with me or any other tips that you might have!

3 comments:

andy said...

I always enjoy learning how other people employ Amazon S3 online storage. I am wondering if you can check out my very own tool CloudBerry Explorer that helps to manage S3 and CloudFront on Windows . It is a freeware.

Troy Tolle said...

Andy, I would try it out, but I am working on a Mac right now. Any chance you are writing a Mac version?

andy said...

Well, Mac client is on our to-do list. But honestly it will take awhile before we make it. We want to make a native Mac client rather than use some multi-platform technology. Let me know what you think about the product if you get a chance to try it out!