Scaling a Web App Takes Forethought
How to Scale a WebObjects App
At Bluedog, we love WebObjects, and there are a number of approaches we take to improve overall scalability -- that is, the number of concurrent users who can connect with a web browser, or via a web service API. We utilize a lot of small instances with a load balancer in front. We try to deploy as a Servlet instead of using WOtaskd (but not always). Also, a simple load balancer that respects sticky sessions works fine. Hardware load balancers tend to be more sophisticated in terms of their load balancing schemes. Generally, we don't use a content caching service like Akamai, but if you can afford it, you can use such a service to fetch once from the web app and then cache the results for a longer period of time.
Most of our web applications are "write once, read many times." Our developers try to avoid caching data that is tied to a session -- i.e. user preferences. Instead, we try to cache the data that is shared across sessions-- i.e. like a document or other shared asset. We also minimize the use of the undo stack in the Enterprise Objects Framework (EOF) configuration, and we avoid using session-based EOEditingContexts. It is a good practice to create one when needed and make sure to clean up after when done with it. Similarly, we aim to use as many stateless WOComponents as possible to minimize the app's memory footprint. If using servlets, we ask our developers to ensure sessions can be fully serialized, to take advantage of your servlet engine's clustering capabilities.
If an app must have a statefull service with fail-over capability, perhaps a database-oriented session store makes sense? It is slower than the default memory version but allows you greater flexibility in load balancing and deployment architectures. Naturally, be careful of EOF relationships. While EOF is great for transactional interactions, it can cause big performance issues if someone inadvertently fetches all records on a large table while trying to access a key path.
Finally, in keeping with our Service Oriented Architecture philosophy, we aim to divide a solution into smaller services, instead of a monolithic application. This provides better flexibility in scaling the components that are under heavy load -- and fosters re-use!