Thursday, January 22, 2015

Speeding up web app deployment in Jetty

When the ProActive Workflows and Scheduling server is started, no fewer than 5 web applications are deployed in the embedded Jetty servlet container. It was taking some time (a few seconds) and we decided to improve it. So, what can be done?

Servlet annotation scanning

By default, Jetty will scan all webapp jars for servlet annotations (those were introduced in the servlet spec version 2.5). Since we don't use any, we can safely disable the scanning, saving time at startup (around 1 second on my machine). This page on eclipse wiki describes how to do it in Jetty. Just set an attribute on your WebAppContext:
WebAppContext webApp = createWebAppContext(...);
webApp.setAttribute("org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern", "^$");

Parallel deployment

By default, Jetty deploys web apps sequentially, but it can be configured to do so in parallel. Here is how:
HandlerList handlerList = createHandlerList(...);
handlerList.setParallelStart(true);
This change shaved off 3 seconds from the startup time on my machine.
Note: In the Jetty version we are using (8.1.16.v20140903), there seems to be a problem in initialization sequence: the deployment starts before the thread pool is started, and hangs. A simple workaround is to start the thread pool manually before the starting Jetty:
org.eclipse.jetty.server.Server server = createHttpServer(...);
QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads);
server.setThreadPool(threadPool);
threadPool.start();
server.start();

Unpack wars

This one is trivial, but the speedup is no less real than for the other ones! We were shipping some of our webapps as wars inside the distribution zip file. So on every startup the wars would be unpacked, and this was taking time. We now changed our release scripts to add unpacked wars in the distribution instead. This simple change further reduced the startup time by 2 seconds.

Moreutils: ts

The moreutils collection contains a nice little tool called ts: a utility to timestamp standard input. The latest version supports the -s switch, which displays the timestaps since the start of the program - very useful for looking at startup times of your app, especially if it prints a few lines of output when is starts.

Result

So here is the final result, with all of the improvements described above, and with timestamps provided by ts:
 $ ./bin/proactive-server -ln 0 -c | ts -s "%.S" 
01.099732 Starting the scheduler...
01.107951 Starting the resource manager...
05.920992 The resource manager with 0 local nodes created on pnp://172.17.42.1:64738/
07.095439 The scheduler created on pnp://172.17.42.1:64738/
07.103600 Starting the web applications...
08.399879 The web application /studio created on http://172.17.42.1:8080/studio
08.399985 The web application /scheduler created on http://172.17.42.1:8080/scheduler
08.400001 The web application /rest created on http://172.17.42.1:8080/rest
08.400014 The web application /rm created on http://172.17.42.1:8080/rm
08.400027 *** Get started at http://172.17.42.1:8080 ***
As you can see, the webapp startup takes only slightly over a second now. Much better!