jueves, 24 de septiembre de 2009

Balanceo de Carga para dos websphere application server 6.1 usando mod_proxy_balancer

Hace varios días que vengo trabajando en un problema que me ha quitado el sueño y la tranquilidad.

Hace como mes y medio empece a leer sobre el tema de balanceo de carga desde Apache usando el mod_proxy_balancer.

http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html

Desde las guías todo parecía sencillo. Sinceramente no estaba muy claro de las modificaciones que se estaban planteando, pero para variar, empece a probar sin terminar de leer la documentación :p

Hice unas pruebas y asumi que todo estaba funcionando bien. El tema se quedó dormido durante algún tiempo, pero luego tuve que retomarlo desafortunadamente con las fechas ya bastante apretadas.

http://www.howtoforge.com/load_balancing_apache_mod_proxy_balancer

Me pareció excelente que se pudiera tener no solamente el balanceo de carga sino la tolerancia a fallos. De manera que si un server se caía, podía seguir operando con el otro server.

-- la version 1 de mi httpd.conf
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
ProxyRequests Off

<Proxy *>
Order deny,allow
Allow from all
</Proxy>

ProxyPass /balancer-manager !
ProxyPass / balancer://clusterWAS/ stickysession=BALANCEID nofailover=On
ProxyPassReverse / http://192.168.15.124:9080/
ProxyPassReverse / http://192.168.15.127:9080/
<Proxy balancer://clusterWAS>
BalancerMember http://192.168.15.124:9080 route=http1
BalancerMember http://192.168.15.127:9080 route=http2
ProxySet lbmethod=byrequests
</Proxy>

<Location /balancer-manager>
SetHandler balancer-manager
Order deny,allow
Allow from all
</Location>
Hice unas pruebas y asumi que todo estaba funcionando. Pero desafortunamente en ese momento no puse mucha importancia al tema de la sesion.

Al tener mi servidor balanceando carga entre los 2 nodos, la mitad de los requerimientos va a un server y la otra mitad al otro. Pero... si entro a mi aplicacion y me firmo. Esto se guarda en una variable de sesion. Y balanceando la carga se pierde.... :(

Es decir..
Pinto pantalla de login (Nodo1)
Recibo parametros de login valido y guardo variables de sesion(nodo2)
Reenvio a pantalla de inicio (Nodo1)

El problema es que en el nodo1, nunca guarde variables asi que asume que no esta firmado y vuelve a pedir la clave.

Lei un poco sobre el tema y hablaba del stickysession.

Ahora que ya entendí les cuento que la famosa stickyession es una cookie con un id de session. Que tiene 2 partes. La session y el route.
CookieJSESSIONID=00009jrrrDW78YKKVP6BTuDqqFg.-1

Esto lo pude ver gracias al pluggin firebug de firefox. Que en la pestaña de red muestra los paquetes enviados.

No obstante no lograba que funcionara en mi esquema.

Yo tengo 2 nodos con Websphere Application Server 6.1. Los 2 tienen la aplicacion instalada y funcionando.

Luego de buscar bastante y hacer bastantes pruebas encontré que la cookie de session se envía diferente en websphere que en tomcat. Y que el apache no la entendía.
CookieJSESSIONID=00009jrrrDW78YKKVP6BTuDqqFg:-1

La diferencia es el ":" en lugar del ".".

https://issues.apache.org/bugzilla/show_bug.cgi?id=42513

No hay un parque para esto en los releases.

Tuve que recompilar el apache para inlcuir la modificación en el modulo. (esto será un post aparte).
El truco no era la recompilada de apache, el truco era, la recompilada en Windows de apache :S

Bueno... luego de recompilado el apache con la recomendación que dan en el bug. Logre que la cookie tuviera el formato adecuado... pero... aun así no funcionaba!

CookieJSESSIONID=00009jrrrDW78YKKVP6BTuDqqFg.-1

Fue luego de esto cuando comprendí que el problema es que el -1 que estaba mostrando debía ser el nombre del nodo.

En algunos post, encontre que este valor es llamado route. y se configuraba en los tomcat como jvmrouteid. En websphere no encontraba nada por el estilo.

Un poco de suerte me llevo a una url donde se miraba el debug de una traza en websphere con balanceo de carga y hablaba de un Clone ID ... http://www-01.ibm.com/support/docview.wss?uid=swg27014498&aid=1

Buscando en la documentación encontre como configurarlo y funcionó.

http://publib.boulder.ibm.com/infocenter/wasinfo/v5r1//index.jsp?topic=/com.ibm.websphere.zseries.doc/info/zseries/ae/rprs_custom_properties.html
Application servers > server1 > Web container > Custom Properties

Para el nodo uno le puse un cloneid de "nodo1" y al otro "nodo2".

Ahora sí. Mis cookies quedaban de la siguiente forma:
para el nodo1:
JSESSIONID=0000gQCnyQMY94sb5oVXZsLU0lR:nodo1

para el nodo2:
JSESSIONID=0000gQCnyQMY94sb5oVXZsLU0lR:nodo2

Con mi apache recompilado y con mis cookies en buen estado procedí a realizar las configuraciones que me hacían falta en el apache.

Primero habilité los módulos necesarios:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so


Luego algunos parámetros generales de la configuracion:
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>


Configuré el balance con mis 2 nodos:
<Proxy balancer://clusterPerfilUno>
BalancerMember http://192.168.15.121:9080 route=nodo1
BalancerMember http://192.168.15.123:9080 route=nodo2
ProxySet lbmethod=byrequests
</Proxy>


donde dice "route=nodo1" es el nombre que haya puesto al cloneid en mi WAS. Luego hago el proxypass en mi aplicacion hacia el balanceo.
La stickysession la hago sobre la cookie que logre setear. Y seteo el reverse para el regreso de las conexiones.

<Location /app>
Order allow,deny
Allow from all
ProxyPass balancer://clusterPerfilUno/app stickysession=JSESSIONID nofailover=On
ProxyPassReverse http://192.168.15.121:9080/app
ProxyPassReverse http://192.168.15.123:9080/app
</Location>


Puse el loglevel en debug para rastrear posibles errores y me sale algo asi:
[Wed Sep 16 16:16:57 2009] [debug] mod_proxy_balancer.c(46): proxy: BALANCER: canonicalising URL //
clusterPerfilUno/app
[Wed Sep 16 16:16:57 2009] [debug] mod_proxy_balancer.c(280): ICON: proxy: BALANCER: Found value 00006BXDRmMTJiopXVx9UnRFUCR:nodo1 for stickysession JSESSIONID
[Wed Sep 16 16:16:57 2009] [debug] mod_proxy_balancer.c(296): proxy: BALANCER: Found route nodo1
[Wed Sep 16 16:16:57 2009] [debug] mod_proxy_balancer.c(579): proxy: BALANCER (balancer://
clusterPerfilUno) worker (http://192.168.15.121:9080) rewritten to http://192.168.15.121:9080/app
[Wed Sep 16 16:16:57 2009] [debug] mod_proxy.c(993): Running scheme balancer handler (attempt 0)
[Wed Sep 16 16:16:57 2009] [debug] mod_proxy_http.c(1920): proxy: HTTP: serving URL http://192.168.15.121:9080/app

Si no tengo buena la cookie recibo el found value (null) for stickysession JSESSIONID.

con esto logre hacer el balanceo de carga usando mod_proxy_balancer con un websphere 6.1 en los nodos.

En los proximos días estaré haciendo pruebas de esto y si encuentro algo mas lo publico.

Espero poder publicar la recompilada del apache sobre windows y también una segunda alternativa que estuve a punto de implementar.

Cabe mencionar que el IHS de IBM es una alternativa que no logre a terminar de evaluar para resolver este problema.

saludos!