Zero-downtime Deployment (and Rollback) in Tomcat; a walkthrough and a checklist

Dear All,

If you thought Tomcat could not get any better, you thought wrong. Tomcat 7 introduces what is called Parallel Deployment. This was contributed by SpringSource/VMWare.

Simply put, parallel deployment is the ability to deploy more than one version of your web application in parallel, making all versions available under the exact same URL.

Think about this for a minute. If you have a new version of your application, you can simply drop it into the Tomcat that is running the old one and it will Just Work™. In fact, they will both work. Tomcat handles all session management and traffic routing between application versions. No need to restart Tomcat. No need to stop processing requests. No need to talk to your boss about downtime. No need for your boss to talk to any customers about downtime.

Let’s see this in action, shall we? Using the commands below you can whip up a minimal web application to demonstrate this feature.

$ mkdir WEB-INF
$ echo "" > WEB-INF/web.xml
$ echo 'old version ' > index.jsp
$ jar cf foo##001.war WEB-INF index.jsp
$ echo 'NEW version ' > index.jsp
$ jar cf foo##002.war WEB-INF index.jsp

You now have two web apps named foo##001.war and foo##002.war. ##001 and ##002 designate the version numbers of the WAR files. Each has their own index page that shows the current time and whether it is the old or the new web application. The people who created this feature chose a surprisingly easy solution for how to tell Tomcat what is an alternate version of what. All you have to do is tack ##<version> onto the WAR’s file name. Simple and effective, if a bit odd-looking.

Now deploy the ’old’ version of the web application.

$ cp foo##001.war apache-tomcat-7.0.12/webapps/

Open a browser, enter the WAR file’s URL (e.g. http://localhost:8080/foo) and watch the time tick by. Note that you do not see the version number on the URL. The page auto-refreshes every second. Beneath the surface, Tomcat will establish a session with your browser. More on that later.

Now deploy the ’new’ version of the web application.

$ cp foo##002.war apache-tomcat-7.0.12/webapps/

Notice how in the already open browser window, the time is still ticking by and it is still showing old version. Open a second browser and in this browser too, open http://localhost:8080/foo. For best results, use an entirely different browser to avoid any session strangeness. I used Safari and Opera for the test.

You should see that the second browser picks up the new web application, while the first browser is still being serviced by the old web application.

Pretty neat, huh?

All-right, so you botched a deployment and want to roll back? Simple, just remove the new version and Tomcat automatically falls back to using the old version. Nice work. Try it now:

$ rm apache-tomcat-7.0.12/webapps/foo##002.war

You will notice the web pages automatically switch to using the old version of the application.

You will have to develop your own deployment strategy. You might choose to let the old versions drain. Once all sessions on the old application have expired, you can remove old deployments from Tomcat. On the other hand, you can just leave the old code deployed. It won’t do any harm.

There are a few things to consider when you want to start using versioned WAR files with your Tomcat server. So before you go off and change the deployment strategy at your company, check off the list below.

  1. Internal caches should be write-through and expire quickly
  2. You need sessions to be enabled
  3. Where does logging go?
  4. Disk files and directories need to be sharable
  5. No TCP socket listeners
  6. Your apps must be able to undeploy

I’ll explain each of these in order. Most are variations on a theme; consider what assumptions your code makes about machine resources.

Internal caches should be write-through and expire quickly

Different version of the same web application each have their own class context. This means that any local caches you have in your web application need to be reviewed. If you cache aggressively and hold on to cached information for a long time, one version of the web application may not see changes that another made.

Picture a situation where both versions of the web application use the same database and both have a local cache to avoid hitting that database. If one version of the web application changes a record in the database, the other won’t see the change until its own cached version of that information has expired.

If you do any in-memory caching in your web application, don’t use parallel deployment until you are sure that the caches will not serve unacceptably stale information.

You need sessions to be enabled

Tomcat uses its own session management to determine what requests should be handled by what version of the web application. If you’ve gone off to implement session handling yourself, or if you switch session handling off in Tomcat, parallel deployment won’t work for you.

Where does logging go?

You probably specified that your logging be written to a log file somewhere. If you do not use the full context name of the application in the log file name, you may end up in a situation where both versions of a web application are writing into the same log file. The problem with that is that you may not know what version of your application generated the output you find in that file.

Disk files and directories need to be sharable

The intention of the designers of Java EE have always intended for web applications to be independent of the underlying machine and file systems. If your application makes use of data files, please take a moment to consider what happens when two versions of your web application start reading and writing them.

In particular, consider that Java’s monitors and locks are confined to a single context. Thus, if you guard access to a file with a lock of some sort, having two versions of that web application means that you have two locks in the JVM, potentially allowing two thread to access it.

No TCP socket listeners

Some applications serve more than just HTTP requests. They have their own TCP socket handlers to serve clients. By deploying more than one version of a web application, you get more than one listener. Obviously this will not work. Only one listener can listen on any given port.

Your apps must be able to undeploy

If you want to be able to roll back botched releases, or if you want to clean out old, unused versions of your web application, your web application needs to undeploy cleanly. Luckily, Tomcat helps you with that too.

I hope these warnings have not put you off using zero-downtime deployment in Tomcat. You may need to solve a few issues for it to work cleanly. But let’s face it, by making your application make fewer assumptions about resources, you get a more robust application anyway.

PS. I like to use SVN revision numbers as a WAR version naming scheme. Thus my WAR files are named foo##<svn revision=””>.war. The only thing to look out for is that versions are compared as strings to determine the version ordering. Thus you may have to zero-pad the version numbers to ensure correct ordering.

Reference: Zero-downtime Deployment (and Rollback) in Tomcat; a walkthrough and a checklist from our JCG partner Kees Jan at the Java Monitor Forum

Happy coding
Byron

Related Articles:

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

One Response to "Zero-downtime Deployment (and Rollback) in Tomcat; a walkthrough and a checklist"

  1. Fernando Franzini says:

    I’m in a very interesting situation. I’m validating the migration tomcat 6 to tomcat 7, so we can use the zero donwtime deploy.
    One of the problematic situations is our cache. As we’ll have two wars running at the same address int tomcat 7… the cache will be doubled! Cache today is inside servlet context.
    The first idea I had was to put the cache within the global JNDI. Thus, all. War can access the same cache in the global JNDI container.
    I work, but the problem came …. When I retrieve an object inserted by another war, the JVM generates another internal identifier for the same class in both wars….and so all my cast crashed!!! Especially those inside equals …..That is, within the cache I have an object of class war within thecom.empresa.Cliente ….., I have the same class does not work just right … but the cast!Any idea how to get around this?

Leave a Reply


four × = 8



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books
Get tutored by the Geeks! JCG Academy is a fact... Join Now
Hello. Add your message here.