apache – tomcat/jboss (mod_jk)


Esta es la receta que uso para conectar un servidor Apache HTTPd con Tomcat, JBoss… cualquier servidor de aplicaciones que entienda el protocolo AJP.

¿En qué consiste esto?

Con esta configuración tendremos que las peticiones HTTP que haga un cliente, se procesarán primero en el servidor HTTP (apache) y dependiendo de la configuración de éste se reenviarán a Tomcat (o JBoss, Resin … o lo que sea, en esta entrada me referiré a todos ellos como Tomcat para abreviar).

¿Qué ventajas tiene?

En mi opinión hay configuraciones que son mucho más simples de aplicar sobre un Apache que sobre un Tomcat. p.ej:

  • Configurar el servicio para que obligue al usuario a usar https para navegar por http://lalala/secured/*
  • Exigir que el usuario se valide contra un directorio LDAP para acceder a la web
  • Permitir el acceso a determinadas zonas de la web en función de la ip/subred de origen

Pero además de facilitar estas tareas de configuración, nos puede aportar algunos beneficios como:

  • Distribuir el trabajo entre dos servicios que no tienen por qué estar en el mismo servidor: Apache maneja el cifrado SSL y Tomcat la aplicación y/o Apache sirve el contenido estático (imágenes, css, javascript) y sólo envía las peticiones de contenido dinámico (jsp’s) a Tomcat, de esta manera no le llegan peticiones de contenido estático a Tomcat y apache actúa de “proxy” de estáticos.
  • Se pueden agrupar distintas aplicaciones que corren en uno o más tomcats, para que se acceda siempre desde la misma URL: p. ej. http://www.domain.com (apache), http://www.domain.com/app1 (tomcat1), http://www.domain.com/app2 (cluster de tomcats2), … con lo que se usa siempre el mismo dominio para todas.
  • Escalado: se pueden añadir más o menos servidores Tomcat, Apache, sin tener que aumentar las prestaciones de un equipo concreto, sino añadiendo equipos o aumentando los recursos allí donde realmente hace falta.

Bueno, los ingredientes para la receta son:

  • uno o varios equipos con RedHat. Por supuesto se puede hacer con cualquier otra distribución, pero para esta receta me referiré a las rutas de los archivos en una RedHat.
  • Apache HTTPd y Tomcat (o JBoss…) instalados
  • algo de tiempo

Manos a la obra.

1.- Comprobaciones
En el equipo donde tenemos Apache necesitaremos los siguientes paquetes:
apr-devel, apr-util, apr-util-devel, httpd-devel, pcre-devel
Y las típicas herramientas para compilar: gcc, make, automake …

2.- Compilando
Bajamos el código del conector mod_jk y:
tar –xzf tomcat-connectors-1.2.XX-src.tar.gz –C /usr/src
cd /usr/src/tomcat-connectors-1.2.XX-src 
cd native/ 
./configure --with-apxs=/usr/sbin/apxs
make
make install

Si todo va bien, tendremos un archivo “mod_jk.so” en /etc/httpd/modules

3.-Configurando Apache
La configuración se divide en tres archivos: workers.properties, jk.conf y httpd.conf.
/etc/httpd/conf/workers.properties:
worker.list=w1
worker.w1.port=8009
worker.w1.host=equipo_tomcat.domain.com
worker.w1.type=ajp13

En este archivo se declara un worker (aka conexión) al equipo equipo_tomcat.domain.com, por el puerto 8009. El protocolo usado será AJP/1.3. En el resto de archivos de configuración se hará referencia a este worker como “w1”. Por supuesto, se puede declarar más de un worker o incluso grupos de workers actuando como loadbalancers.

/etc/httpd/conf.d/jk.conf:
LoadModule    jk_module  modules/mod_jk.so 
JkWorkersFile /etc/httpd/conf/workers.properties
JkShmFile     /var/log/httpd/mod_jk.shm 
JkLogFile     /var/log/httpd/mod_jk.log 
JkLogLevel   error 
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

Este archivo corresponde a la configuración del módulo “mod_jk”. Las líneas relevantes son para indicar la ruta de “mod_jk.so” y la configuración de workers, aunque también se especifican la ruta para logs y formato.

/etc/httpd/conf/httpd.conf:

...
JkMount /app w1
JkMount /app/* w1
...

Al añadir estas líneas a la configuración de apache, cuando se solicite algun recurso bajo /app, se redireccionará a Tomcat. Este formato de la directiva JkMount es sólo si se usa fuera de un Location o Directory. Si se usa dentro de éstos, como no tiene sentido especificar “/app” porque eso ya viene dado por Location/Directory se haría:

...
<Location /app>
...
JkMount w1
...
</Location>
...

4.-Configurando Tomcat
Sólo revisar que el puerto AJP es el 8009 que es el valor por defecto, sino, deberíamos actualizar el archivo worker.properties. En Tomcat se define en “conf/server.xml” y en JBoss en “server/default/deploy/jbossweb-tomcat55.sar/server.xml”. Opcionalmente se puede desactivar el conector HTTP para garantizar que las peticiones HTTP pasarán siempre por Apache.

5.-Y Luego?
Podemos combinar la autenticación LDAP y conexión con mod_jk en el mismo Directory/Location .. para que se solicite un usuario del LDAP para entrar a la aplicación web. La ventaja es que no requiere modificar el código de la aplicación web, pero por contra, no se tendrán roles ni grupos de usuarios en la aplicación web.

Se puede usar un archivo worker.properties como éste:
..
# se definen 3 workers
worker.list=w1,w2,lb1

# w1: instancia 1 de Tomcat
worker.w1.port=8009

worker.w1.host=server1.domain.com

worker.w1.type=ajp13

worker.w1.lbfactor=1

# w2: instancia 2 de Tomcat
worker.w2.port=8009
worker.w2.host=server2.domain.com

worker.w2.type=ajp13

worker.w2.lbfactor=4


worker.lb1.type=lb
worker.loadbalancer.balanced_workers=w1,w2
worker.loadbalancer.sticky_session=false
..
Si desde la configuración de Apache usamos el worker lb1, realmente se está llamando a un grupo de workers que trabajan como balanceadores de carga. Cada uno de ellos apunta a una instancia distinta de Tomcat (aunque a la misma aplicación web) que puede estar instalada en distintos equipos. Tambien se puede cambiar el lbfactor para ponderar el balanceo: el equipo más potente (server2.domain.com) sirve más peticiones.

O también podemos complementar el worker.properties anterior con las directivas:
worker.w1.redirect=w2
worker.w2.disabled=True


Así, si desde apache usamos el worker w1 en el momento que éste no pueda contactar con server1.domain.com lo hará a través de w2 y por tanto con server2.domain.com. Pero sólo se accedería a server2 en caso de que w1 no pueda contactar con server1.

Podemos usar la directiva JkUnMount para separar el contenido estático. Si sabemos que todas las peticiones a /app/images/* son imágenes gif/png y tal, pero no hay ningún archivo JSP o similar, usaríamos algo como:
...
JkMount /app w1
JkMount /app/* w1
JkUnMount /app/images/ w1
JkUnMount /app/images/* w1
...
Así, apache sólo pasará las peticiones a Tomcat que no sean al subdirectorio images/. Éstas las responderá directamente apache. Por contra, en el servidor apache deberemos crear un subdirectorio images bajo DocumentRoot y replicar el contenido del directorio de la webapp en él. Esto puede optimizar muchísimo los tiempos de respuesta de la aplicación.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: