viernes, 22 de enero de 2010

Comprimiendo el acceso a base de datos


Problema
Con aplicaciones win, a menudo ocurre que tenemos el servidor de base de datos en otro lugar fisico, conectado a traves de VPN o similar. Para este tipo de aplicaciones en Genexus se incorporó la posibilidad de generar en 3 capas, donde hay un servidor de aplicaciones que hace el trabajo pesado contra la base de datos y al cliente solo llegan los datos que se muestran al usuario (al menos en teoría).

Cuando se tiene una aplicacion 2 capas, pasar a 3 capas puede implicar muchos dolores de cabeza, principalmente por procesos que no se pueden ejecutar en el servidor porque interactuan con el usuario, ademas de pantallas que se quedan bloqueadas y otros problemas.

En más de un cliente fue necesario instalar aplicaciones Java 2 capas que se conectaban a un servidor en VPN, pero fue hace muy poco que me puse a investigar el volumen de datos que pasaba por la VPN para ver si habia forma de optimizar la performance. Ahí encontré que hay volúmenes grandes, por ejemplo reportes que trasmiten más de 1MB de datos o transacciones que dada la cantidad de consultas que hacen a la base de datos generan mucho tráfico.

Solución
Dado que Genexus es quien genera los programas, a simple vista parece que no hay mucho que podamos hacer para optimizar el tráfico en una aplicación win 2 capas, pero dimos con una solución sencilla y con un costo de implementación muy bajo, grandes beneficios y estable. Se trata de entunelar y comprimir la conexión entre la aplicación y la base de datos.

Del lado del cliente se precisa un programa que pueda escuchar una conexión TCP/IP común, comprimirla y trasmitirla a un servidor de compresión/descompresión, el primero a su vez se encarga de descomprimir la respuesta del servidor. En la otra punta de la conexión lenta (VPN) está el servidor de descompresión que hace las operaciones análogas, descomprimir las conexiones entrantes para mandarlas limpias al DBMS y comprimir la respuesta del DBMS para que vuelva al cliente.

Las 2 partes de la solución (servidor y cliente) fueron implementadas en Java, que gracias a su excelente manejo de streams y threads obtuvo una implementación muy sencilla, estable y de buen rendiminto. El algoritmo de compresión fue zlib que es parte de la api de Java, lo cual también ayudo a no agregar dependencias.

Cliente
El cliente está embebido en la aplicación y levanta automáticamente al poner el parámetro compression=true en la url de conexión. Simplemente parsea la url buscando el parámetro y si lo encuentra levanta una instancia del cliente en la PC cliente y cambia la url de conexión para que se conecte a esta instancia en vez de conectarse al servidor real.

Servidor
Se instala en el servidor de DBMS o en otro servidor que esté en la misma LAN. Para que esté siempre disponible se instaló como servicio de Windows utilizando JSL (altamente recomendable). El único requerimiento es tener una JVM instalada.

Resultados
Los resultados fueron muy buenos, en términos generales puede decirse que se bajaron a la tercera parte los tiempos de respuesta y como ya se anticipó, con una solución muy estable y con un costo bajo. Hay que tener en cuenta que en todos los clientes la velocidad no superaba los 256kbps es de suponer que a medida que se mejora la velocidad los beneficios disminuyen.

También hay que notar que estos algoritmos agregan procesamiento, especialmente al servidor que escucha las peticiones de todos los clientes. En nuestro caso no era un problema, en una parte porque los clientes no son muchos y en otra parte porque los servidores tienen buena capacidad de procesamiento.

Links de interés
IPTunnelManager - Una herramienta paga que permite hacer túneles comprimidos y encriptados, instalando uno en cada punta de la conexión lenta se podrían comprimir las conexiones al DBMS.