jueves, 26 de febrero de 2015

Acelerando el arranque de Tomcat 7

Regresamos con un mini-artículo sobre como mejorar los tiempos de arranque del servicio Tomcat, específicamente de la distribución de Tomcat 7 para el Framework Dinámica, que por correr aplicaciones creadas con este framework, no necesita JSPs, TagLibs, anotaciones de Servlet Spec 3.x ni otros artificios. Dinámica es minimalista, usa un solo Servlet (el Controller) y algunos filtros/listeners, nada ajeno a la especificación de servlets 3.0. Por este motivo hay varias cosas que se pueden desactivar en Tomcat para que arranque considerablemente más rápido.

La velocidad de arranque del servicio es importante para mantener la interrupción del mismo en un mínimo aceptable, sea por controles de cambio o contingencias.

Paso 1

En ${tomcat.home}/conf/catalina.properties se definen las reglas de scanning de anotaciones en los JARs, es el primer punto a tocar. La configuración por defecto pecha bastante el tiempo de arranque haciendo revisiones innecesarias (para Dinámica) en los JARs. El tiempo de arranque en nuestro Tomcat 7 con 4 WebApps instaladas es el siguiente:

[2015-02-25 16:01:57] INFORMACIËN: Initializing ProtocolHandler ["http-bio-80"]
[2015-02-25 16:01:57] INFORMACIËN: Initialization processed in 300 ms
[2015-02-25 16:01:57] INFORMACIËN: Arrancando servicio Catalina
[2015-02-25 16:01:57] INFORMACIËN: Starting Servlet Engine: Apache Tomcat/7.0.59
[2015-02-25 16:01:57] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\admin de la aplicaci¾n web
[2015-02-25 16:01:57] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\devel de la aplicaci¾n web
[2015-02-25 16:01:57] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\nws de la aplicaci¾n web
[2015-02-25 16:01:57] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\ROOT de la aplicaci¾n web
[2015-02-25 16:02:00] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\ROOT has finished in 2.367 ms
[2015-02-25 16:02:00] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\nws has finished in 2.517 ms
[2015-02-25 16:02:00] INFORMACIËN: [Dinamica] SecurityFilter started for context: AdminConsole
[2015-02-25 16:02:00] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\admin has finished in 2.690 ms
[2015-02-25 16:02:01] INFORMACIËN: WSSERVLET14: inicializando el servlet de JAX-WS
[2015-02-25 16:02:01] INFORMACIËN: WSSERVLET12: inicializando el listener de contexto de JAX-WS
[2015-02-25 16:02:01] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\devel has finished in 3.220 ms
[2015-02-25 16:02:01] INFORMACIËN: Starting ProtocolHandler ["http-bio-80"]
[2015-02-25 16:02:01] INFORMACIËN: Server startup in 3256 ms

Lo que vamos a hacer es desactivar el scanning de los JARs, configurando estos parámetros con los valores mostrados abajo:

tomcat.util.scan.DefaultJarScanner.jarsToSkip=*.jar
org.apache.catalina.startup.ContextConfig.jarsToSkip=*.jar
org.apache.catalina.startup.TldConfig.jarsToSkip=*.jar

Con este no se desactiva el uso de anotaciones muy útiles, como @WebService y @MultipartConfig.
Si reiniciamos Tomcat obtenemos estos tiempos:

[2015-02-25 16:09:21] INFORMACIËN: Initializing ProtocolHandler ["http-bio-80"]
[2015-02-25 16:09:21] INFORMACIËN: Initialization processed in 287 ms
[2015-02-25 16:09:21] INFORMACIËN: Arrancando servicio Catalina
[2015-02-25 16:09:21] INFORMACIËN: Starting Servlet Engine: Apache Tomcat/7.0.59
[2015-02-25 16:09:21] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\admin de la aplicaci¾n web
[2015-02-25 16:09:21] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\devel de la aplicaci¾n web
[2015-02-25 16:09:21] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\nws de la aplicaci¾n web
[2015-02-25 16:09:21] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\ROOT de la aplicaci¾n web
[2015-02-25 16:09:22] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\ROOT has finished in 610 m
s
[2015-02-25 16:09:22] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\nws has finished in 770 ms

[2015-02-25 16:09:22] INFORMACIËN: [Dinamica] SecurityFilter started for context: AdminConsole
[2015-02-25 16:09:22] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\admin has finished in 1.01
1 ms
[2015-02-25 16:09:23] INFORMACIËN: WSSERVLET14: inicializando el servlet de JAX-WS
[2015-02-25 16:09:23] INFORMACIËN: WSSERVLET12: inicializando el listener de contexto de JAX-WS
[2015-02-25 16:09:23] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\devel has finished in 1.59
1 ms
[2015-02-25 16:09:23] INFORMACIËN: Starting ProtocolHandler ["http-bio-80"]
[2015-02-25 16:09:23] INFORMACIËN: Server startup in 1617 ms

Una reducción de aproximadamente el 50%, nada mal.

Paso 2

A nivel de cada WebApp es necesario desactivar el scanning de TLDs, No sirve hacerlo en el context.xml global de Tomcat 7, ya lo probamos y no tiene efecto. Es necesario hacerlo en el context.xml privado de cada WebApp que está en /META-INF. Las WebApps creadas con Dinámica para correr en Tomcat usan la definición de su pool de conexiones a BD dentro de este archivo. Y el plugin del Framework para crear WebApps en Eclipse ya incluye esta entonación cuando crea el proyecto. Se trata de añadir el siguiente elemento (resaltado en amarillo):

<Context processTlds="false">

... el pool se define aquí ...

</Context>

Antes de esta optimización podríamos ver con JConsole el tiempo gastado en procesar TLDs aunque no los estemos usando:


Luego de aplicar el cambio en TODAS las WebApps instaladas, observamos que el tiempo del atributo tldScanTime=0 para cada WebApp.


Y el log de arranque del servicio muestra el resultado final de la entonación:

[2015-02-25 16:11:34] INFORMACIËN: Initializing ProtocolHandler ["http-bio-80"]
[2015-02-25 16:11:34] INFORMACIËN: Initialization processed in 297 ms
[2015-02-25 16:11:34] INFORMACIËN: Arrancando servicio Catalina
[2015-02-25 16:11:34] INFORMACIËN: Starting Servlet Engine: Apache Tomcat/7.0.59
[2015-02-25 16:11:34] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\admin de la aplicaci¾n web
[2015-02-25 16:11:34] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\devel de la aplicaci¾n web
[2015-02-25 16:11:34] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\ROOT de la aplicaci¾n web
[2015-02-25 16:11:34] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\nws de la aplicaci¾n web
[2015-02-25 16:11:34] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\nws has finished in 441 ms

[2015-02-25 16:11:34] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\ROOT has finished in 441 m
s
[2015-02-25 16:11:34] INFORMACIËN: [Dinamica] SecurityFilter started for context: AdminConsole
[2015-02-25 16:11:34] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\admin has finished in 561
ms
[2015-02-25 16:11:35] INFORMACIËN: WSSERVLET14: inicializando el servlet de JAX-WS
[2015-02-25 16:11:35] INFORMACIËN: WSSERVLET12: inicializando el listener de contexto de JAX-WS
[2015-02-25 16:11:35] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\devel has finished in 1.15
3 ms
[2015-02-25 16:11:35] INFORMACIËN: Starting ProtocolHandler ["http-bio-80"]
[2015-02-25 16:11:35] INFORMACIËN: Server startup in 1179 ms

¡El tiempo de arranque se redujo en 64%! Otra ventaja de usar el estilo Dinámica de programación simple, sin las complicaciones asociadas usualmente al desarrollo web con Java.

Plataforma utilizada:

  • Tomcat 7.0.59
  • Java 1.8 update 31 x64
  • Windows 7 Home Premium x64


Esperamos les resulte de utilidad este mini blog, sobre todo a los suscriptores del Framework (Dinámica se vende por suscripción), aprovechamos de celebrar con esto los 11 años de Dinámica en producción, utilizado a escala global en docenas de proyectos que traspasan dominios de negocios y le ha permitido nutrirse y robustecerse como herramienta de hiper productividad.