Which Deployment Option Would You Use For a Mission Critical Application?
You have the following deployment options in Java EE (J2EE/5/6):
- Deploying an EAR / WAR to a multi-project or dedicated server
- Cluster deployment: deployment units get spread across the nodes, you get HTTPSession and @Stateful Bean failover
- Cluster deployment, but no replication or failover. You get easy distribution and management (deactivating, disabling) of deployment units
- Dynamic environment: your application is split across loose-coupled modules, which could be managed independently
- Minimization of moving parts - simplicity is the key!
- Very simple upgrade and maintenance strategies - the system should always be in consistent state.
- Dead simple monitoring and deployment - operations are rarely interested in our geeky frameworks, switches and whistles.
- Avoidance of third party frameworks and libraries - they are faster EOL than you may think.
- We deployed not only the application, but also the application server with already installed application AND JDK as a zip with hardcoded classpath
- The application consisted with as few as only possible external libraries, parts or frameworks. We started with JDK 1.6 then expanded the search to Java EE 6 (or lower versions)
- Although we had logical packages and components, we tried to deploy the application as a "BLOB" e.g. maven-with-dependencies does a nice job here. The fewer jars you have - the less can go wrong.
- We didn't used a cluster but also didn't relied on the HA-qualities of the HTTPSession and SFSB in particular.
- A simple load balancer, sometimes a slightly more sophisticated strategy, distributed the load across mostly independent servers (with sticky sessions were possible).
The strategy above has an interesting side-effect: you can not only upgrade your application, but also your appserver AND the JDK, just by replacing a folder or extracting a zip. After re-routing the traffic and killing the process or virtual machine - you can consistently and atomically update not only the app, but also the whole environment. Interestingly a "mission critical" strategy is fully compatible with building maintainable software. [See chapter 1 in "Real World Java EE Patterns - Rethinking Best Practices" for more in depth transactions, clustering, state, optimistic concurrency discussion]
Deploying JDK and AppServer as part of the application is IMHO not a good option. If you always do so you end up with many different versions of JDK and AppServer (maybe also different products) and that's not manageable.
But maybe we could talk about that when we meet next time ;-)
Posted by Simon Martinelli on March 18, 2010 at 07:18 PM CET #
it really depends on context whether it is a good option or not. If your developing a product its perfect, if your are running a cloud-service its a nightmare. Although then the deployment might be even coarser like e.g. ec2, where the smallest chunk is the whole operating system with your software and not the JVM or even a module,
We should discuss that next time - fully agreed!,
Posted by Adam Bien on March 18, 2010 at 08:28 PM CET #
love your post. Summarizes many of the options, you see on-site these days.
Also don't like the idea of distributing the complete environment. This will not work in more mature operational environments ;)
I am missing the virtualization aspects. What I do see more an more is the use of virtualization as the primary mission critical/scaling option. (It could be worth some thoughts, why this could be wrong ;))
Agree with the minimal framework strategy. As mentioned on one of your other posts. It still is something you can't avoid completely.
Posted by Markus on March 19, 2010 at 09:19 AM CET #
In practice everything is a trade-off. If beneficial, I use from time to time jakarta-commons, joda time and other frameworks from that caliber. But I don't use any framework pro-actively.
A framework usage should clearly (>10%) pay-off.
thanks for your comment,
Posted by Adam Bien on March 19, 2010 at 11:36 AM CET #
Interesting approach which I can see working in environments that are dedicated to hosting just the one simple Java EE application. But I do have a number of questions of how this would work in a more complex environment:
- How would you do this in a shared environment? Or with WebSphere or WebLogic where zipping up the whole appserver is not really an option.
- How do you handle the parts of the deployment that are outside of the Java EE container (see http://blog.xebia.com/2009/07/08/so-what-is-a-deployment-really/)?
- How do you tailor this ZIP to the different environments (test, acceptance, production, etc.)?
Posted by Vincent Partington on March 19, 2010 at 12:40 PM CET #
1. E.g. WinZip will not manage to compress WAS - too huge with too many files :-). I would set-up then identical servers (which could be spinned-off with a script etc.), or even set up a virtual image with everything on it. WLS and WAS have also their own provisioning solutions.
2. Setting-up a database, with external dependencies, is a bit off-topic of this post. If you have many servers to set-up, I would use Puppet from reductive labs for it (http://reductivelabs.com/products/puppet/)
3. Even without ZIP I did the following: for the application view all the servers were configured identically it means: the same JNDI-names. Although the names were the same, the resources were configured to point to somewhere else. In Glassfish case only the domain.xml was different, we did the same for JBoss - in that case more files were affected. In one case we build a perl script for managing that (it wasn't me, rather than the operations). I would try to use maven for tailoring, or other automated solution.
Thanks for the comment - we should discuss this interesting topic on e.g. JavaONE?
Posted by Adam Bien on March 19, 2010 at 02:27 PM CET #
Thought on different environments -- we use DNS names. The DB server is always called DB, we use /etc/hosts or a real DNS server to control where that goes. This keeps it entirely external to the application and app server.
Posted by Randy on March 19, 2010 at 07:20 PM CET #
perfect - its even KISSer :-). Then you don't even have to change the appserver configuration. It of course requires, that the credentials for e.g. the resource user has also be identical in all stages.
Posted by Adam Bien on March 19, 2010 at 10:29 PM CET #
How do you handle existing, sticky sessions to a server that is supposed being updated? Since you have no state replication between the servers all users have to start over when being routed to a new server.
How did you solve this problem or did you just accept it?
Posted by Tom on March 26, 2010 at 02:48 PM CET #
you cannot just ignore sticky sessions :-). Good news: every load balancer I know is able to do that.
thanks for your comment!,
Posted by Adam Bien on March 26, 2010 at 03:22 PM CET #
- User A has Sticky Session bound to Server A
- User A authenticates on Server A
- Server A is shutdown for an upgrade or just crashes
- User A is forwarded to Server B
- Server B doesn't know User A
- User A has to login again
(Authentication is just an example, could be other things such as ViewState)
I hope I could explain the problem better than last time.
Posted by Tom on March 26, 2010 at 04:04 PM CET #
o.k. I just don't rely on the state in the HTTPSession. In worst case the user has to re-login. It is in most cases acceptable.
Thanks for your fast response!,
Posted by Adam Bien on March 26, 2010 at 10:59 PM CET #