Soporte de Web Sockets en Apache Web Server (httpd) sobre un contenedor Docker

0
11018

En este tutorial vamos a probar el soporte de web sockets en un Apache Web Server «dockerizado».

0. Índice de contenidos.


1. Introducción

En tutoriales anteriores hemos visto como podemos implementar una conexión bidireccional entre cliente y servidor
estableciendo un canal de comunicación en tiempo real con el soporte de Web Sockets y:

En todos esos ejemplos el servidor estaba directamente expuesto al cliente pero ¿y si el servidor está fuera de la DMZ
y tenemos un proxy inverso delante?, y ¿si necesitamos montar nuestra aplicación en cluster activo/activo y queremos dar
soporte de balanceo a las peticiones vía Web Sockets?

En este tutorial vamos a configurar httpd (Apache Web Server) para dar soporte y hacer pruebas de redirección de peticiones ws (Web Sockets) con balanceo de carga, inicialmente en un entorno no productivo.

Remarco que las pruebas las vamos a ejecutar en un entorno no productivo porque además vamos a hacerlas en un contenedor docker de httpd, que nos va a servir
«para cacharrear» sin tener ninguna intención inicial de guardar o externalizar esa configuración para su uso en otros entornos, aunque como hemos
visto recientemente en el tutorial de introducción a docker no sería muy complejo hacerlo.

2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 15′ (2.3 GHz Intel Core i7, 16GB DDR3).
  • Sistema Operativo: Mac OS Mavericks 10.9.4
  • Boot2docker 1.6.2
  • Apache Web Server httpd 2.4.12
  • Apache Tomcat 8.0.20


3. Httpd con Docker.

Asumiendo que tenemos docker o boot2docker instalado, en función del SO en el que estemos trabajando, la instalación de la imagen oficial de
httpd pasa por la ejecución del siguiente comando:

Con ello nos bajaremos la última versión publicada de la imagen que, a día de hoy, incorpora un httpd 2.4.12.

Podemos comprobar la descarga de la imagen ejecutando el comando de listado de imágenes:

El siguiente paso es arrancar un contenedor basado en esa imagen, proporcionando un nombre descriptivo y, como es posible
que tengamos un apache en local corriendo, mapeando el puerto local 9091 contra el puerto 80 del contenedor

Usando boot2docker tenemos que lanzar el siguiente comando para comprobar la ip en la que se ha levantado el contenedor.

Ahora podemos acceder a través del navegador para comprobar que se encuentra levantado:

httpd-websockets-docker-00

Con el siguiente comando podemos listar los contenedores creados basados en las imágenes y comprobar el estado de los mismos

Parece que lo tenemos listo para empezar «a cacharrear» pero en este punto, tenemos un primer problema,
la imagen oficial de Apache Web Server al arrancar levanta el proceso httpd, si accedemos al contenedor
y paramos el proceso httpd también se para el contenedor.
La recomendación en este punto es construir nuestra propia imagen basada en la de httpd proporcionando
una configuración externa, bien basándonos en un Dockerfile o mapeando un directorio local contra el
directorio de configuración de httpd en el contenedor; pero no vamos a invertir inicialmente tiempo en esto,
nuestro objetivo es disponer de un apache 2.4 para hacer pruebas de configuración no preparar un entorno de producción.

A continuación paramos el contenedor:

Y lo borramos:

Al comando inicial con el que creamos el contenedor basándonos en la imagen vamos a añadirle los siguientes parámetros

  • -it: para acceder por consola a la shell del contenedor,
  • -p: por cambiar el puerto inicial que proponíamos al 81,
  • el comando bash al final para que no se levante el proceso establecido por defecto para la imagen, sino que simplemente permita el acceso a la consola,

Una vez ejecutado, podemos lenvantar manualmente el Apache Web Server:

Si, por cualquier motivo paramos el contenedor siempre podemos volver a levantarlo manualmente

Y podemos «engancharnos» a la consola de bash del contendor con el siguiente comando (dos veces INTRO):

Ya podemos parar y arrancar tanto el contendor como el httpd que nos proporciona internamente el mismo, si bien, nos
encontramos con un segundo problema, no tenemos un editor que nos permita modificar fichero alguno desde el contenedor;
las imágenes están pensadas para consumir pocos recursos y ocupar poco espacio con lo que tienen lo mínimo imprescindible
para que después las amplies; ya digo que lo normal es externalizar la configuración de los procesos, en este caso httpd,
en ficheros externos al contenedor para que levantar uno o varios dockers por entorno sea homogéneo, pero para esta prueba
no vamos a hacer eso, vamos a instalar un editor en el contenedor.

La imagen se ha generado en base una debian con lo que vamos a ejecutar los siguientes comandos:

Hay que tener en cuenta que todo lo que hemos hecho se perderá si borramos el contenedor y, a partir de aquí,
podemos ejecutar el siguiente comando:

para hacer una prueba rápida de edición de la página de indice de Apache.

Si levantamos el proceso httpd:

y accedemos a través del navegador al puerto configurado veremos los cambios

httpd-websockets-docker-01

Aparte de cacharrear en este punto ya hemos aprendido o consoliado conceptos sobre docker.


4. Web sockets httpd proxy.

Vamos a configurar el soporte de web sockets en Apache Web Server y lo primero que debemos hacer es habilitar
los módulos correspondientes en la configuración de httpd para que los soporte. Accediendo al fichero de configuración

Habilitaremos los siguientes módulos:

Y, para probar, en cualquier punto del mismo fichero, puede ser después de la declaración del primer <Directory />
podemos añadir la siguiente configuración

La IP 172.20.10.3 es la de mi máquina local que está visible para el contenedor.

El orden en el que declaramos las URLs de mapeo es importante puesto que debemos declararlas de mayor a menor granularidad y, por regla general las que mapean el protocolo ws serán más granulares y, como consecuencia, las primeras en declararse.

Las pruebas las estamos haciendo con el proyecto montado con el soporte de spring-messaging, que expone un primer servicio /notifications/info por http que devuelve la información del Web Socket, como la URL es más granular debe declararse el primero.

Si ahora reiniciamos el proceso, podríamos comprobar que ya no es necesario acceder a la aplicación por el puerto del Apache Tomcat, puesto que está correctamente mapeado por el Apache Web Server.

Si no funcionase correctamente, una manera de comprobar que los módulos que están cargados es ejecutando el siguiente comando:

5. Web sockets en cluster con htttp.

Ahora vamos a suponer que tenemos la aplicación levantada en dos tomcats, en la misma máquina con distintos puertos.

Lo primero que vamos a hacer es habilitar el monitor del balanceador, podriamos no hacerlo pero buena gana de ponernos una venda en los ojos

A continuación vamos a configurar tres balanceadores con sus correspondientes URLs de mapeo que
coinciden tanto en orden como en contenido con lo configurado anteriormente, solo que ahora redirigen a los balanceadores:

Si realizamos varias peticiones desde distintos clientes podemos comprobar,
accediendo al monitor del balanceador en la URL http://192.168.59.103:81/balancer-manager, como las peticiones
se reparten entre los distintos tomcats.

httpd-websockets-docker-02

6. Referencias.


7. Conclusiones.

Debemos tener en cuenta que, con lo visto, un cliente a través del Apache Web Server está conectado a
un Web Socket de un Apache Tomcat, la carga está repartida entre los distintos servidores pero
simplemente con la configuración anterior las notificaciones desde los servidores a los clientes tendrían que
ejecutarse desde todos los nodos del balanceador, no hemos configurado una replica de la sesión de web sockets
entre los distintos nodos del cluster. ¿Será el contenido de otra entrada en el blog?

Sin necesidad de mantener una réplica de sessiones y disponiendo un repositorio de información común, como podría ser:

  • una base de datos, cada nodo podría «monitorizar» una tabla de notificaciones para remitirlas a todos sus clientes conectados, o
  • una cola de mensajería como se plantea en esta entrada de activemq,
    de tal modo que nodo podría suscribirse a un topic de notificaciones y despachar el mensaje recibido de la cola, a sus clientes conectados.

Un saludo.

Jose

Dejar respuesta

Please enter your comment!
Please enter your name here