Apache, Módulo JK (mod_jk) y JBoss

1
54823

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





Enestetutorial os vamos a enseñar a instalar un servidor apache,instalar el módulo JK para comunicar con dos servidoresJBoss en cluster, para conseguir balanceo de carga yreplicación de sesión (el balanceo de carga nos loproporcionará el módulo JK de apache, y lareplicación de la sesión JBoss). Suponemos que disponemosde tres máquinas. En dos de ellas tendremos instaladas unservidor JBoss 4.0.5 que arrancaremos en cluster. En la otramáquina tenemos instalado el servidor apache 2.2.4 . La arquitectura es la siguiente:


Arquitectura






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
 )

Descarga de mod-jk

A continuación, modificaremos el nombre del fichero que nos acabamos de descargar y le llamaremos:
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

Hemosconfigurado para balancear las consolas de JBoss, así como una aplicación que crearemos posteriormente cuyo context-path es
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:


Consola de apache



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:

https://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:

.


<attribute name=»ClusterConfig»>


    

        <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>




….















En este mismo fichero se configura la replicación de sesión, en principio no tocaremos nada.

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)


Consola JMX

Seleccionaremos el MBean jboss:service=DefaultPartition para ver la configuración del cluster:

Consola JMX-cluster

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:

Error de conexión

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:

copiando en farm

Vemos que se ha desplegado en el cluster. Vamos a acceder a la aplicación a través de apache:


Imagen





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:


Imagen



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




















1 Comentario

  1. 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

Dejar respuesta

Please enter your comment!
Please enter your name here