I'm working with an existing web application developed in Ruby with a MySQL back-end, but I think the generic hardware topology question will apply to a wide variety of server architectures.
I'm looking for a document / web resource explaining and detailing current best practice relating to organising the hardware within a server farm for delivering a web based application with a database back-end.
The current architecture is as follows;
HTTP Server (Apache)
|
Application Servers x 8 (Unicorn / Ruby-on-Rails)
|
MySQL Back-end (Master)
\
\
MySQL Slave (primarily for performing backups)
The proposed architecture needs to be more scalable than the above, including a load balancer in front of multiple HTTP servers, splitting the app servers between the HTTP server(s), multiple MySQL slaves to server read only requests (which will be controlled by changes within the application software)
The main aim is to have a more resilient system, using current best practice, and this is what has been suggested so far.
But, if anyone can suggest a resource for best practice within this type of environment, or propose an architecture which will give the resiliency, performance and scalability that we are after, I'd be most grateful :)
Dave
Scalability extends beyond the hardware layer and well into the application-layer. The ability of an environment to grow to bigbiglots is dependent to a great degree in the ability of the software at each layer to handle fault and maintain a coherent state across the entire environment. If the database driving your entire environment can't be sharded, you have introduced a scalability stopper by using that database. That kind of thing.
Amazon has some white-papers on developing for their cloud, and several of them are generally applicable to any scalable infrastructure.
http://aws.amazon.com/whitepapers/
There are some high-level principles you need to keep in mind when scaling:
Don't just use a load-balancer, use a trio of load-balancers that present as a single LB so that if any one fails, the others can pick up the load.
The web/app servers should have user-state available on all nodes, so if a user is pushed to another web/app server their session is preserved. Best case, all state can be served from all servers.
There should be redundant routers in your network, so you can take one down without stopping all traffic. HSRP is one protocol to enable this.
Your database-plan must include how far you will scale the one DB server before you start sharding, and start developing with sharding in mind once you get close to that point.
Caching layers (memcached) may be needed in your environment for performance reasons.
Once you get large enough, you need to plan on how you'll host your environment from multiple separate locations (such as US West and US East, or US West and Europe) via Anycast or GeoIP. Moving data between the separate locations will be a challenge, and you need to start developing against that assumption once you get close to needing separate locations.
Ruby itself has some scaling issues, focusing on its ability (or not) to take advantage of multiple processors on servers. The capabilities are there, but rather new so not well understood in the dev community yet (or so I gather). As Ruby matures, some of these issues will go away.
Thanks for the great explanation; the issue of scalability can be reduced in case of relational databases through database load balancer. It can scale linearly, and support many more concurrent users at a fraction of the response time, all without any changes to your application so these are quite suitable for web based or web applications.