Wednesday, September 24, 2008
Brian Goetz opens our eyes again to the world of concurrency fallacies in basic everyday code. In his latest article Brian reintroduces us to something every Java web developer either know or should know but sometimes forget. You must code cautiously when using ServletContext and HttpSession to hold state. It makes the code ugly as sin, but it will bite you in the ass later if you don't. I know he was focusing on the thread-safety of the matter, but he did elude to problems with replication of data across a cluster. Too often we design with the intent that an app will remain small and a single server will suffice. Sometimes we'll stick some data for performance reasons in the ServletContext and expect it to always be present and current. However, the ServletContext is not replicated across a cluster like HttpSession objects. In this case you must resort to more involved solutions like: 1) Always hit the database: It becomes a performance drag, but will work. 2) In some cases a local non-distributed cache will work. In this case each node has its own cache of data it is utilizing, but the cache need not be replicated as the data will be retrieved from persistent storage. However, cache flushes must be distributed so that common items in all node's caches will be flushed when needed. OSCache does this very well. 3) Use the HTTP Session instead of the ServletContext. This one always feels wrong to me, but I guess in some limited circumstances is simple and useful. The problem is that mostly static data will exist in many HTTPSession objects instead of a more centralized location. You'll be using lots more memory, serialization and replication will take longer, and its a bloated solution. Use very sparingly. 4) I've never tried these but they seem interesting. Look into EHCache to see if it supports cache replication, or the Terracotta "network attached memory". While I'm certain these can scale, but what's the performance tradeoff to achieve the scalability.