APACHE, MODULO JK (mod_jk) y JBOSS
Los ejemplos de este tutorial están hechos con el siguiente entorno de desarrollo:
-
Jboss Eclipse IDE.
-
JDK 1.5
-
JBoss 4.0.5 GA
-
Apache 2.2.4

En este tutorial noenseñaré a instalar ni Apache ni JBoss, ya que norequiere su instalación ningún conocimiento especial. Os muestro los enlaces donde descargar ambas aplicaciones:
http://labs.jboss.com/portal/jbossas/download
http://httpd.apache.org/download.cgi
Lo que si necesitaremos descargar es el mod_jk y os enseñaré a instalarlo:
INSTALACIÓN Y CONFIGURACIÓN DEL MÓDULO JK
Desde
http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/
seleccionaremos la carpeta en función de donde estéinstalado nuestro servidor apache (en mi caso win32) seleccionaremos laversión 1.2.21 (versión estable en el momento deltutorial) y elegiremos la librería a descargar en función de la versión de nuestro apache (en nuestro caso:
mod_jk-apache-2.2.4.so )

mod_jk.so
y lo copiareremos a la ruta de nuestro servidor apache: <APACHE_HOME>/modules
Una vez copiado, abriremos el fichero de configuración de apache:
<APACHE_HOME>/conf/httpd.conf e incluiremos la siguiente línea al final del fichero:
# Include mod_jk configuration file
Include conf/mod-jk.conf
Crearemos el fichero
mod-jk.conf
tal y como hemos indicado en el fichero de configuración anterior en:
<APACHE_HOME>/conf . Debajo muestro el contenido del fichero.
# Load mod_jk module
# Specify the filename of the mod_jk lib
LoadModule jk_module modules/mod_jk.so
# Where to find workers.properties
JkWorkersFile conf/workers.properties
# Where to put jk logs
JkLogFile logs/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel info
# Select the log format
JkLogStampFormat «[%a %b %d %H:%M:%S %Y]»
# JkOptions indicates to send SSK KEY SIZE
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat
JkRequestLogFormat «%w %V %T»
# Mount your applications
JkMount /application/* loadbalancer
# You can use external file for mount points.
# It will be checked for updates each 60 seconds.
# The format of the file is: /url=worker
# /examples/*=loadbalancer
JkMountFile conf/uriworkermap.properties
# Add shared memory.
# This directive is present with 1.2.10 and
# later versions of mod_jk, and is needed for
# for load balancing to work properly
JkShmFile logs/jk.shm
# Add jkstatus for managing runtime data
<Location /jkstatus/>
JkMount status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
Ahora, crearemos el fichero
workers.properties
donde configuraremos los nodos a los que vamos a balancear la carga en
<APACHE_HOME>/conf
:
# Define list of workers that will be used
# for mapping requests
# The configuration directives are valid
# for the mod_jk version 1.2.18 and later
worker.list=loadbalancer,status
# Definimos el nodo Nodo1
# Puerto del conector ajp de nuestro tomcat (JBoss)
worker.nodo1.port=8009
# Ip del nodo 1.
worker.nodo1.host=192.168.1.7
worker.nodo1.type=ajp13
# Peso de nuestro nodo. A más peso, mas peticiones recibe.
worker.nodo1.lbfactor=1
# Definimos el nodo Nodo2
worker.nodo2.port=8009
worker.nodo2.host=192.168.1.13
worker.nodo2.type=ajp13
worker.nodo2.lbfactor=1
# Load-balancing behaviour
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=nodo1,nodo2
# Status worker for managing load balancer
worker.status.type=status
Ahora, crearemos el fichero
uriworkermap.properties
donde configuraremos las aplicaciones a balancear en
<APACHE_HOME>/conf
:
# Simple worker configuration file
# Mount the Servlet context to the ajp13 worker
/jmx-console=loadbalancer
/jmx-console/*=loadbalancer
/web-console=loadbalancer
/web-console/*=loadbalancer
/ejemplo=loadbalancer
/ejemplo/*=loadbalancer
ejemplo.
El conector mod_jk usasticky-sessions por defecto para balancear la carga, lo que quieredecir que siempre intentará enviar al mismo nodo todas las peticiones con la misma sesión (esto es configurable)
.
Yatenemos instalado y configurado Apache y el módulo jk.Arrancaremos apache para comprobar que no hemos comentido ningún error:

Podemos ver en la parte posterior como nos indica que el mod_jk está cargado.
CONFIGURACIÓN DE LOS NODOS EN JBOSS
Para información sobre temas de cluster en JBoss podéis ver el tutorial:
http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=HAScheduler
Lo primero que haremos es configurar los nodos de JBoss para arrancaren cluster. Para trabajar en cluster, lo haremos en la configuración
all
(
run.bat -c all
) de JBoss.
Configuraremos el cluster en ambas máquinas. Lo primero queharemos será editar el fichero: <JBOSS_HOME>/server/all/deploy/
cluster-service.xml
,para configurar el cluster (usaremos UDP multicast). Si no lo hemostocado nunca o la instalación es nueva en ambos casos esprobable que no haga falta tocar nada. Os muestro a continuaciónla parte que nos interesa del fichero en ambas máquinas del cluster:
….
<!– The JGroups protocol configuration –>
<attribute name=»PartitionConfig»>
<Config>
<UDP
mcast_addr=»${jboss.partition.udpGroup:228.1.2.3}» mcast_port=»45566″
ip_ttl=»${jgroups.mcast.ip_ttl:8}» ip_mcast=»true»
mcast_recv_buf_size=»2000000″ mcast_send_buf_size=»640000″
ucast_recv_buf_size=»2000000″ ucast_send_buf_size=»640000″
loopback=»false»/>
<PING timeout=»2000″ num_initial_members=»3″
up_thread=»true» down_thread=»true»/>
<MERGE2 min_interval=»10000″ max_interval=»20000″/>
<FD_SOCK down_thread=»false» up_thread=»false»/>
<FD shun=»true» up_thread=»true» down_thread=»true»
timeout=»10000″ max_tries=»5″/>
<VERIFY_SUSPECT timeout=»3000″ num_msgs=»3″
up_thread=»true» down_thread=»true»/>
<pbcast.NAKACK gc_lag=»50″ retransmit_timeout=»300,600,1200,2400,4800″
max_xmit_size=»8192″
up_thread=»true» down_thread=»true»/>
<UNICAST timeout=»300,600,1200,2400,4800″ window_size=»100″ min_threshold=»10″
down_thread=»true»/>
<pbcast.STABLE desired_avg_gossip=»20000″ max_bytes=»400000″
up_thread=»true» down_thread=»true»/>
<FRAG frag_size=»8192″
down_thread=»true» up_thread=»true»/>
<pbcast.GMS join_timeout=»5000″ join_retry_timeout=»2000″
shun=»true» print_local_addr=»true»/>
<pbcast.STATE_TRANSFER up_thread=»true» down_thread=»true»/>
</Config>
<!– Alternate TCP stack: customize it for your environment, change bind_addr and initial_hosts –>
<!–
<Config>
….
….
Comprobad que tenéis comentada la parte de TCP y descomentada laparte de UDP. Comprobad que ambas máquinas tienen la misma IP y puerto multicast:
mcast_addr=»${jboss.partition.udpGroup:228.1.2.3}» mcast_port=»45566″
Comprobad en la parte superior del fichero que ambas máquinas pertenecen al mismo grupo del cluster (mismo nombre):
<!– Name of the partition being built –>
<attribute name=»PartitionName»>
${jboss.partition.name:DefaultPartition}
</attribute>
….
Ahora configuraremos el tomcat de JBoss de ambos nodos para indicarleque vamos a usar mod-jk. Además, vamos a desactivar losconectores http:8080 de ambos nodos para impedir que se acceda directamente a los servidores de aplicaciones.
Editaremos el fichero:
JBOSS_HOME/server/all/deploy/jbossweb-tomcat50.sar/
server.xml
y modificaremos lo siguiente:
En ambos nodos:
Comentaremos esta parte:
<!– A HTTP/1.1 Connector on port 8080
<Connector port=»8080″ address=»${jboss.bind.address}»
maxThreads=»250″ strategy=»ms» maxHttpHeaderSize=»8192″
emptySessionPath=»true»
enableLookups=»false» redirectPort=»8443″ acceptCount=»100″
connectionTimeout=»20000″ disableUploadTimeout=»true»/>
–>
Comprobaremos que esta parte está descomentada:
<!– A AJP 1.3 Connector on port 8009 –>
<Connector port=»8009″ address=»${jboss.bind.address}»
emptySessionPath=»true» enableLookups=»false» redirectPort=»8443″
protocol=»AJP/1.3″/>
En el nodo 1, añadiremos lo siguiente a la etiqueta
engine
:
….
<Engine name=»jboss.web» defaultHost=»localhost»
jvmRoute=»nodo1″
>
….
En el nodo 2:
….
<Engine name=»jboss.web» defaultHost=»localhost»
jvmRoute=»nodo2″
>
….
Ahora editaremos el fichero:
JBOSS_HOME/server/all/deploy/jbossweb-tomcat50.sar/META-INF/
jboss-service.xml
y le indicaremos que vamos a usar mod-jk en ambas máquinas:
….
<attribute name=»UseJK»>
true
</attribute>
….
A continuación, vamos a configurar el cluster en el tomcat de JBoss de ambas máquinas.
Editaremos el fichero:
JBOSS_HOME/server/all/deploy/tc5-cluster.sar/META-INF/
jboss-service.xml
y comprobaremos que la parte de configuración del clusterestá igual en ambos nodos y tiene comentada la parte de TCP y descomentada la de UDP:
.
…
<config>
<UDP
mcast_addr=»${jboss.partition.udpGroup:230.1.2.7}»
mcast_port=»45577″
ucast_recv_buf_size=»20000000″
ucast_send_buf_size=»640000″
mcast_recv_buf_size=»25000000″
mcast_send_buf_size=»640000″
loopback=»false»
max_bundle_size=»64000″
max_bundle_timeout=»30″
use_incoming_packet_handler=»true»
use_outgoing_packet_handler=»true»
ip_ttl=»${jgroups.mcast.ip_ttl:2}»
down_thread=»false» up_thread=»false»
enable_bundling=»true»/>
<PING timeout=»2000″
down_thread=»false» up_thread=»false» num_initial_members=»3″/>
<MERGE2 max_interval=»100000″
down_thread=»false» up_thread=»false» min_interval=»20000″/>
<FD_SOCK down_thread=»false» up_thread=»false»/>
<FD shun=»true» up_thread=»false» down_thread=»false»
timeout=»20000″ max_tries=»5″/>
<VERIFY_SUSPECT timeout=»1500″
up_thread=»false» down_thread=»false»/>
<pbcast.NAKACK max_xmit_size=»60000″
use_mcast_xmit=»false» gc_lag=»50″
retransmit_timeout=»300,600,1200,2400,4800″
down_thread=»false» up_thread=»false»
discard_delivered_msgs=»true»/>
<UNICAST timeout=»300,600,1200,2400,3600″
down_thread=»false» up_thread=»false»/>
<pbcast.STABLE stability_delay=»1000″ desired_avg_gossip=»50000″
down_thread=»false» up_thread=»false»
max_bytes=»400000″/>
<pbcast.GMS print_local_addr=»true» join_timeout=»3000″
down_thread=»false» up_thread=»false»
join_retry_timeout=»2000″ shun=»true»/>
<FC max_credits=»2000000″ down_thread=»false» up_thread=»false»
min_threshold=»0.10″/>
<FRAG2 frag_size=»60000″ down_thread=»false» up_thread=»false»/>
<pbcast.STATE_TRANSFER down_thread=»false» up_thread=»false»/>
</config>
….
Ahora no nos queda más que arrancar los servidores JBoss.Comprobaremos que las máquinas del cluster se ven. Para empezar,entraremos en la consola jmx de alguno de ellos (no sabemos cual será ya que el balanceador nos llevará a alguno de ellos)

Podemos ver las dos máquinas del cluster. Podéiscomprobar que no podemos acceder directamente al puerto 8080 denuestros Jboss porque los hemos deshabilitado (probamos por ejemplo la máquina 192.168.1.7:8080:
Hemos comprobado que el balanceo está funcionando. Vamos ahora a probar la replicación de sesión.
APLICACIÓN WEB CON REPLICACIÓN DE SESIÓN.
Vamos a crearnos unapequeña aplicación web que sólo va a contener unindex.jsp como página de inicio. La aplicación la empaquetaremos en un fichero llamado ejemplo.war.
Os muestro el código de
index.jsp:
METO EN SESION UN CONTADOR.<br>
<%
Integer contador = (Integer)session.getAttribute(«CONTADOR»);
if(contador==null) {
contador = new Integer(0);
}
contador = new Integer(contador.intValue()+1);
session.setAttribute(«CONTADOR»,contador);
System.out.println(«Salgo en la consola del servidor que sirve la jsp»);
%>
<br>
El contador vale:
<%=session.getAttribute(«CONTADOR»)%>
Os muestro el web.xml:
<?xml version=»1.0″ encoding=»ISO-8859-1″?>
<!DOCTYPE web-app
PUBLIC «-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN»
«http://java.sun.com/j2ee/dtds/web-app_2_4.dtd»>
<web-app>
<distributable/>
<display-name>Ejemplo</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Indicamos con el tag distributable que queremos habilitar la replicación de sesión para nuestra aplicación.
Necesitamos también el descriptor jboss-web.xml para configurar la manera de la replicación:
<jboss-web>
<replication-config>
<replication-trigger>SET_AND_NON_PRIMITIVE_GET</replication-trigger>
<replication-granularity>SESSION</replication-granularity>
<replication-field-batch-mode>true</replication-field-batch-mode>
</replication-config>
</jboss-web>
Empaquetamos la aplicación en ejemplo.war:
– ejemplo.war
+ WEB-INF/
– web.xml
– jboss-web.xml
- index.jsp
La desplegamos en la granja de servidores jboss, es decir, la copiamos en el directorio
JBOSS_HOME/server/all/
farm
de alguno de ellos:
Vemos que se ha desplegado en el cluster. Vamos a acceder a la aplicación a través de apache:

En la consola del servidor que elija el balanceador se mostrará el mensaje que sacamos con System.out.
Accedemos varias veces para aumentar el contador hasta 10 (veréis como el nodo elegido siempre es el mismo)
Parad ahora el servidor que estaba sirviendo las peticiones. Y probad a entrar de nuevo a la página:

Comprobaréis dos cosas:
1. Ahora el balanceador detecta que el servidor alque dirigía las peticiones está caido y lo redirige al otro nodo (mirad la consola del que está levantado)
2. El contador no empieza en uno, sino que se mantiene la sesión valiendo 11.
Bueno, pues parece que no es tan dificil conseguir una arquitectura medianamente profesional. Espero que os haya gustado.
No obstante si necesitáis ayuda, ya sabéis:
http://www.autentia.com
Hi all,
I hope than any can help me with this problem.
The topology that I try to do is that:
[App-1]====>(Post request)====>[Balancer]=====>[App2 – JBoss instance]
* The parameter sended via Post is a XML that represents an entity
The JBoss server is listen the port 8009 but mi App2 have a service that is listen the port 8900, this service is configured with Mule-ESB.
I try this configurations:
1.- Worker port: 8900
In this case App2 receive an unexpected message (see result.png)
2.- Worker port: 8009
The message is sended to App2 by balancer (I know that because the message in «access.log» is: «127.0.0.1 – – [23/Aug/2011:15:00:47 -0500] «POST /orderReceiver HTTP/1.1″ 404 988») but this is not attended by App2
3.- Worker port: 8009 and App2 listen the same port 8009
The same result as scenario #1
In case #1, when I set «JkLogLevel debug» in mod-jk.conf I see that the XML is sendend but preceded by some meta-information, I suspect that this information is nos recognized by my service and for this reason I obtain the result shown in result.png
sending to ajp13 pos=4 len=184 max=8192
0000 12 34 00 B4 02 04 00 08 48 54 54 50 2F 31 2E 31 – .4……HTTP/1.1
0010 00 00 0E 2F 6F 72 64 65 72 52 65 63 65 69 76 65 – …/orderReceive
0020 72 00 00 09 31 32 37 2E 30 2E 30 2E 31 00 FF FF – r…127.0.0.1…
0030 00 09 6C 6F 63 61 6C 68 6F 73 74 00 00 50 00 00 – ..localhost..P..
0040 03 A0 0E 00 1E 4A 61 6B 61 72 74 61 20 43 6F 6D – …..Jakarta.Com
0050 6D 6F 6E 73 2D 48 74 74 70 43 6C 69 65 6E 74 2F – mons-HttpClient/
0060 33 2E 31 00 A0 0B 00 09 6C 6F 63 61 6C 68 6F 73 – 3.1…..localhos
0070 74 00 A0 08 00 03 34 33 30 00 06 00 05 6E 6F 64 – t…..430….nod
0080 6F 32 00 0A 00 0F 41 4A 50 5F 52 45 4D 4F 54 45 – o2….AJP_REMOTE
0090 5F 50 4F 52 54 00 00 04 32 31 35 37 00 0A 00 10 – _PORT…2157….
00a0 4A 4B 5F 4C 42 5F 41 43 54 49 56 41 54 49 4F 4E – JK_LB_ACTIVATION
00b0 00 00 03 41 43 54 00 FF 00 00 00 00 00 00 00 00 – …ACT……….
ajp_send_request::jk_ajp_common.c (1684): (nodo2) request body to send 430 – request body to resend 0
ajp_send_request::jk_ajp_common.c (1789): (nodo2) sending 430 bytes of request body
sending to ajp13 pos=4 len=436 max=8192
0000 12 34 01 B0 01 AE 3C 55 73 61 67 65 52 65 71 75 – .4…….
…
0160 64 65 72 52 65 71 75 65 73 74 3E 0A 20 20 3C 64 – …………..2011-
0180 30 38 2D 32 33 20 31 35 3A 32 34 3A 34 38 2E 34 – 08-23.15:24:48.4
0190 34 37 20 43 4F 54 3C 2F 64 61 74 65 52 65 71 75 – 47.COT………….
I’ve made a trivial app that recive and print a GET request and print it in console, this app works fine. I deploy this app in a default Tomcat (with default ports).. I can’t test this app with POST request.
So, my questions are:
1.- mod_jk allow the POST request? It’s necessary to do any change in my configuration to receive POST request?
2.- Exist any difference between the original POST and the POST received by Mule-ESB?
3.- It’s necessary to do any other configuration in my JBoss instance?
I’ve atached my configuration files.
Any help is welcome,
Alexis Gamarra Cano