Scalability – proxying heavyweight webapps

February 23, 2009 | by Geoff


We recently had a tech talk about scalability as it pertains to developing web applications. Many best practises were discussed including load balancing, clustering, highly-available databases, eventually consistent application designs.

In most web applications, the proportion of dynamic requests (application logic) to static requests (images, javascript, css, html, flash) is usually quite low. As a result, it can be quite taxing on your application server if most of its time is spent serving static content to users.

Looking at some real statistics over two months from one of the systems we developed shows that out of 2,522,507 total requests, only 395,742 were for dynamic application data. That is 15% of all requests were dynamic, the remainder being requests for images, stylesheets or flash components.


System architecture
A common technique in web systems is to have a lightweight web server reside between your backend web application (usually a heavyweight beast) and the world at large. This allows the lightweight web server to take load off the heavyweight backend web application leaving it to focus on generating all the fun dynamic content for your application. The application server threads do not get tied up serving static content this improving system utilisation.

A lightweight proxy server (e.g. Apache HTTPD with mod_proxy) can be configured to improve performance by serving up static content fast and ensure correct headers are set such that upstream content proxies and end user browser software will cache the static content appropriately, further improving performance for repeat visitors.



Example Implementation
We setup a system with Apache HTTPD as the lightweight proxy server which sits in front of our application servers. The two are connected via mod_proxy. This Apache module provides a bridge between the two servers so that they may seamlessly interact to provide different components for a single starting web request. Essentially, all dynamic content is generated by the app server, this may reference images and other static content which will be served by the proxy server.

An example configuration is provided below:

# create an alias for static content to be served
Alias /static/ "/location/of/content"

RewriteEngine on

# static content should not be proxied to tomcat - just serve it up directly
# we re-write the URL and rely on the ALIAS defined above for '/static/'
# Essentially, we rewrite all requests for static content to use the
# hard wired alias which should point to content on disk
RewriteCond %{REQUEST_URI}  .*\.(jpg|png|gif|swf|flv|css|js|html)$
RewriteRule ^/(.+) /static/$1 [PT,L]

# assume our Java app is deployed to the 'app' context
RewriteRule ^/app/(.+) ajp://localhost:8009/app/$1 [P]

ProxyPass /app/ ajp://java-server:8009/app/ timeout=300
ProxyPassReverse /app/ ajp://java-server:8009/app/

<Proxy *>
AddDefaultCharset off
Order deny,allow
Allow from all
</Proxy>

This particular example uses mod_proxy_ajp to connect Apache HTTPD to a Java application server. However, this technique can be used to front many different backends using the Apache mod_proxy module including applications developed targeting Perl/mod_perl, IIS/ASP.NET or even ColdFusion.

Bookmark and Share

Tags: , ,

Leave a Reply