Configurar la alta disponibilidad

La solución estándar de cliente de la API de WhatsApp Business se ejecuta en un solo contenedor de Docker. Tener varios contenedores de Docker en ejecución genera problemas y puede provocar la prohibición temporal de la cuenta. En esta guía te orientaremos en la configuración de la alta disponibilidad, lo que te permitirá tener contenedores de Docker suspendidos por si el contenedor de Docker principal sufre una interrupción.

Esta solución de alta disponibilidad requiere una instalación de instancia única del cliente de la API de WhatsApp Business existente que se ejecute sobre esta. Si aún no has configurado el número de teléfono del cliente de la API de WhatsApp Business, revisa la documentación de instalación antes de continuar con la solución.

Información general

Un clúster de alta disponibilidad requiere, como mínimo, dos nodos maestros y dos nodos de aplicación principal, como se puede apreciar en el diagrama siguiente:

Clúster de alta disponibilidad

Se recomienda que todos los nodos se ejecuten en equipos o bastidores diferentes para evitar que errores de un equipo o bastidor afecten a varios nodos al mismo tiempo.

Puesta en marcha

Al poner en marcha un clúster, todos los nodos maestros competirán para hacerse con el arrendamiento maestro y convertirse en el principal. Solo un nodo lo conseguirá y los demás serán maestros secundarios. Si existe un número N de nodos maestros en el clúster, habrá un maestro principal y N-1 maestros secundarios. El objeto maestro principal es responsable del registro, la actualización del esquema de base de datos, la transmisión de cambios de configuración, las estadísticas de la base de datos de informes, la administración de clústeres, etc. Si el objeto maestro principal muere y pierde el arrendamiento maestro, otros m=maestros secundarios competirán para ocupar la posición del objeto maestro principal.

Si un objeto maestro se convierte en principal, cargará primero la tabla del mapa de particiones de la base de datos para saber cuál es el nodo de aplicación principal primario actual. Si no existe ningún nodo de aplicación principal en el clúster, el objeto maestro principal promocionará un nodo de aplicación principal secundario en buen estado al nodo de aplicación primario y actualizará la tabla del mapa de particiones en la base de datos para que el nodo de aplicación web pueda buscar el nodo de aplicación principal al que enviará las solicitudes de API. De este modo, aunque todos los nodos maestros estén inactivos, se podrán atender las solicitudes de API en los nodos de aplicación principal para lograr una alta disponibilidad.

Cuando un nodo de aplicación principal se inicia, se ejecuta como un nodo de aplicación principal secundario hasta que el objeto maestro principal lo promociona para que sea el nodo de aplicación principal primario que se conectará al servidor de WhatsApp. Después de eso, será responsable de gestionar las solicitudes de la API.

Supervisión basada en base de datos

Cada uno de los nodos de aplicación principal actualizará la base de datos cada minuto para reclamar su ejecución. El objeto maestro principal comprobará la base de datos regularmente para detectar nodos de aplicación principal en mal estado. Si un nodo de aplicación principal primario no actualiza la base de datos durante más de 2 minutos, el objeto maestro principal considera que está en mal estado y promociona otros nodos de aplicación principal para que sean el primario. De este modo, el tiempo de inactividad es de unos 2 minutos.

Supervisión basada en latidos

Si un clúster tiene más de un objeto maestro en ejecución, la supervisión basada en latidos detecta errores de nodos más rápido que la supervisión basada en base de datos. En la supervisión basada en latidos, todos los maestros son responsables de supervisar los nodos de aplicación principal, para lo cual deben enviarles latidos cada 5 segundos (configurado mediante heartbeat_interval). Si un nodo de aplicación principal primario no ha respondido al maestro principal y a un maestro secundario en 30 segundos (configurado mediante unhealthy_interval), se considera en mal estado. En este caso, el maestro principal promocionará un nodo de aplicación principal secundario en buen estado para que sea el nodo de aplicación principal primario. De este modo, el tiempo de inactividad es de unos 30 segundos de forma predeterminada. Puedes reducir el valor de unhealthy_interval si prefieres un tiempo de inactividad menor. Consulta la documentación de configuración para ver cargas útiles de ejemplo.

Configuración inicial

En un clúster de alta disponibilidad, existen tres tipos de nodos: aplicación web, maestro y aplicación principal. Se pueden iniciar por separado en máquinas distintas, pero deben estar en la misma red para poder comunicarse entre sí.

Un nodo de la aplicación web es el responsable de gestionar el tráfico de la API como el contenedor de la aplicación web original. Un nodo de la aplicación principal es el responsable de gestionar el tráfico de mensajería de y hacia WhatsApp. Finalmente, un nodo maestro es el responsable de supervisar los nodos de la aplicación principal del clúster, de modo que, si uno de los nodos de la aplicación principal falla, se redirija el tráfico a otro nodo de la aplicación principal y, así, conseguir una alta disponibilidad. Puede haber varios nodos de aplicación web, aplicación principal y maestros en el clúster.

Ya no se hace referencia a los nodos activos como nodos esclavos. Ahora se llaman nodos de la aplicación principal.

Nota: En la mayoría de los casos, para los entornos de producción, la base de datos debe ejecutarse en un servidor físico aparte desde los contenedores de aplicación principal y aplicación web. Para conseguir alta disponibilidad real, es recomendable ejecutar los contenedores maestros, de aplicación web y de aplicación principal en distintas máquinas físicas.

Configurar un sistema de archivos compartido para mensajes multimedia

Si no te interesan los mensajes multimedia, puedes omitir este paso.

Para admitir el envío y recepción de mensajes multimedia, es necesario configurar un sistema de archivos NFS y montarlo en un directorio local en todos los nodos de la aplicación web, la aplicación principal y objetos maestros. Asegúrate de que el directorio compartido tenga permisos de lectura/escritura.

Comando de montaje NFS de ejemplo:

mkdir new-local-directory
mount -t nfs nfs_server_IP_addr:/share_directory new-local-directory

Instalación con Docker Compose

Esta guía requiere Docker, una plataforma de contenedor que te permite ejecutar el cliente de la API de WhatsApp Business. Docker Compose también es necesario. Docker Compose se incluye con Docker para macOS y Windows, pero requiere una instalación independiente en Linux.

Configuración de desarrollador con un único servidor

  1. Instala Docker en tu sistema.
  2. Si Docker Compose no se incluye con la instalación de Docker, instálalo.
  3. Descarga los archivos de configuración multiconnect-compose.yml y db.env: WhatsApp_Configuration_Files.zip.
  4. Abre una consola y navega hasta el directorio en el que guardaste los archivos descargados.
  5. Si tienes una instalación de MySQL en ejecución, cambia los valores del archivo db.env para que reflejen tu configuración de MySQL. Si no tienes MySQL instalado, los archivos multiconnect-compose.yml y db.env tienen una configuración predeterminada para mostrar una instancia en un contenedor local.
  6. Asegúrate de que no haya contenedores de conexión única en ejecución antes de iniciar varios contenedores para obtener alta disponibilidad:
      docker-compose -f your-single-connect-yml-filename stop
    
  7. Ejecuta el comando siguiente en la consola:
    docker-compose -f multiconnect-compose.yml up
    Obtendrás alguna salida mientras el script descarga las imágenes de Docker y lo configura todo. Para ejecutar los contenedores en segundo plano, utiliza el parámetro -d:
    docker-compose -f multiconnect-compose.yml up -d

Una vez completados estos pasos, asegúrate de que todos los contenedores se ejecuten mediante el comando siguiente:

docker-compose ps

De forma predeterminada, el contenedor de la aplicación web se ejecutará en el puerto 9090.

Configuración de producción con varios servidores para cada contenedor

  1. Instala Docker en tus sistemas.
  2. Si Docker Compose no se incluye con tus instalaciones de Docker, instálalo.
  3. Descarga los archivos de configuración multiconnect-coreapp.yml, multiconnect-master.yml, multiconnect-webapp.yml y db.env: WhatsApp_Configuration_Files.zip. Guarda cada uno de estos archivos en el servidor respectivo.
  4. En cada servidor, abre una consola y desplázate hasta el directorio en que has guardado los archivos descargados.
  5. En una configuración de producción, es recomendable utilizar una instancia independiente de MySQL. Si ya tienes una, cambia los valores del archivo db.env para que reflejen tu configuración de MySQL.
  6. Asegúrate de que no haya contenedores de conexión única en ejecución antes de iniciar varios contenedores para obtener alta disponibilidad:
    docker-compose -f your-single-connect-yml-filename stop
    
  7. Ejecuta los comandos siguientes en la consola para cada máquina correspondiente:

    La variable de entorno EXTERNAL_HOSTNAME debería ser una dirección IP o un nombre de host que sea accesible desde las máquinas que ejecutan otros contenedores. Los puertos expuestos en un archivo YML de servicio deben estar abiertos a conexiones de máquinas que ejecutan otros contenedores. Por ejemplo, los puertos definidos como COREAPP_EXTERNAL_PORTS en multiconnect-coreapp.yml deben estar abiertos para el tráfico entrante en el host que ejecuta los contenedores de coreapp.

    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml up # on the Coreapp server
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml up # on the Master server
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml up # on the Webapp server
    Obtendrás alguna salida mientras el script descarga las imágenes de Docker y lo configura todo. Para ejecutar los contenedores en segundo plano, utiliza el parámetro -d:
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml up -d # on the Coreapp server
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml up -d # on the Master server
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml up -d # on the Webapp server

Una vez completados estos pasos, asegúrate de que todos los contenedores se ejecuten mediante el comando siguiente:

EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml ps # on the Coreapp server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml ps # on the Master server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml ps # on the Webapp server

De forma predeterminada, no podrás ejecutar varias instancias del mismo servicio (por ejemplo, 2 aplicaciones principales en el mismo host) debido a un conflicto de puertos del host. Para evitar un conflicto de puertos, debes modificar el archivo YML de servicio respectivo, en este caso multiconnect-coreapp.yml, para mostrar distintos puertos de host para cada instancia como se muestra a continuación:

ports:
- "HOST_PORT_RANGE:6250-6253"

De forma predeterminada, el contenedor de la aplicación web se ejecutará en el puerto 9090.

Actualización

Configuración de desarrollador con un único servidor

El archivo multiconnect-compose.yml tiene campos que indican las versiones del contenedor. Por ejemplo:

services: ... waweb: image: docker.whatsapp.biz/web:v2.19.4 ... master: image: docker.whatsapp.biz/coreapp:v2.19.4 ... wacore: image: docker.whatsapp.biz/coreapp:v2.19.4

Para actualizar una instalación, cambia los números de versión en el archivo multiconnect-compose.yml:

services: ... waweb: image: docker.whatsapp.biz/web:v2.19.7 ... master: image: docker.whatsapp.biz/coreapp:v2.19.7 ... wacore: image: docker.whatsapp.biz/coreapp:v2.19.7

A continuación, reinicia los contenedores de Docker:

docker-compose -f multiconnect-compose.yml up

Configuración de producción con varios servidores para cada contenedor

Los archivos YAML tienen campos que indican las versiones de los contenedores. Por ejemplo:

services: ... waweb: image: docker.whatsapp.biz/web:v2.19.4
services: ... wacore: image: docker.whatsapp.biz/coreapp:v2.19.4

services: ... master: image: docker.whatsapp.biz/coreapp:v2.19.4

Para actualizar una instalación, cambia los números de versión en los archivos correspondientes:

services: ... waweb: image: docker.whatsapp.biz/web:v2.19.7
services: ... wacore: image: docker.whatsapp.biz/coreapp:v2.19.7

services: ... master: image: docker.whatsapp.biz/coreapp:v2.19.7

A continuación, reinicia los contenedores de Docker:

EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml up # on the Coreapp server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml up # on the Master server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml up # on the Webapp server

Conexión de volúmenes existentes

Si tienes volúmenes multimedia de una instalación anterior, reemplaza la definición de volumen siguiente en los archivos YAML:

volumes:
  whatsappData:
      driver: local
  whatsappMedia:
      driver: local

por:

volumes:
  whatsappData:
      external: true
  whatsappMedia:
      external: true

Montajes de enlace

Solo se recomienda esta opción si quieres mantener un volumen de montaje de enlace existente.

Si quieres montar una ruta de host directamente (una ubicación existente del host) en el contenedor, puedes hacerlo cambiando la línea del volumen dentro de la sección del servicio para que apunte a la ruta del host.

wacore:
    volumes:
        /filepath/waent/data:/usr/local/waent/data
        /filepath/wamedia:/usr/local/wamedia

Desinstalación

Configuración de desarrollador con un único servidor

Tendrás que repetirlo para todas las máquinas en las que tengas nodos en ejecución.

Si necesitas restablecer tu entorno de desarrollo mediante la eliminación de todos los contenedores, ejecuta el siguiente comando desde el directorio que contiene el archivo multiconnect-compose.yml:

docker-compose -f multiconnect-compose.yml down

Para deshacerte de todos los volúmenes definidos en el archivo multiconnect-compose.yml, además de los contenedores, ejecuta down con el parámetro -v:

docker-compose -f multiconnect-compose.yml down -v

Configuración de producción con varios servidores para cada contenedor

Si necesitas restablecer tu entorno de desarrollo mediante la eliminación de todos los contenedores, ejecuta el siguiente comando desde el directorio que contiene el archivo YAML en cada servidor:

EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml down # on the Coreapp server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml down # on the Master server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml down # on the Webapp server

Para deshacerte de todos los volúmenes definidos en los archivos YAML, además de los contenedores, ejecuta down con el parámetro -v:

EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml down -v # on the Coreapp server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml down -v # on the Master server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml down -v # on the Webapp server

Registros de solución de problemas

Para obtener registros de solución de problemas, ejecuta este comando en tus servidores:

  docker-compose logs > debug_output.txt