Configurar alta disponibilidad

La solución estándar del cliente de la API de WhatsApp Business funciona en un único contenedor de Docker. Si se ejecutan varios contenedores de Docker, se generarán problemas que provocarán que se prohíba la cuenta de manera temporal. Esta guía te orientará en la configuración de alta disponibilidad, que permite tener contenedores de Docker en espera en caso de que el contenedor de Docker principal quede inactivo.

Esta solución de alta disponibilidad requiere que la instalación de instancia única existente del cliente de la API de WhatsApp Business se ejecute en ella. Si no configuraste aún el número de teléfono del cliente de la API de WhatsApp Business, consulta la documentación de instalación antes de intentar poner en práctica esta solución.

Información general

Un clúster de alta disponibilidad requiere al menos dos nodos maestros y dos nodos de la aplicación principal, como se muestra en el siguiente diagrama:

Clúster de alta disponibilidad

Se recomienda que todos los nodos se ejecuten en máquinas o racks diferentes para evitar que, si se produce una falla en una sola máquina o rack, esto no afecte a varios nodos al mismo tiempo.

Inicio

Cuando se inicia un clúster, todos los nodos maestros compiten para obtener la asignación principal y convertirse en primarios. Solo un nodo lo logrará, y los demás se volverán nodos maestros secundarios. Si el clúster posee un número N de nodos maestros, habrá un nodo maestro primario y N-1 nodos maestros secundarios. El nodo maestro primario es responsable de las acciones de registro, actualización de esquema de base de datos, transmisión de cambios de configuración, estadísticas de bases de datos de informes, administración de clústeres, etc. Si el nodo maestro muere y pierde la asignación principal, otros m=nodos maestros secundarios competirán para asumir el lugar de nodo maestro primario.

Cuando un nodo maestro se convierte en primario, en primer lugar cargará la tabla del mapa de fragmentos de la base de datos para aprender cuál es la aplicación principal primaria actual. Si en el clúster no hay una aplicación principal primaria, el nodo maestro primario promoverá una aplicación principal secundaria saludable al lugar de aplicación principal primaria y actualizará la tabla del mapa de fragmentos en la base de datos, de modo que la aplicación web podrá buscar a qué nodo de la aplicación principal debe enviar las solicitudes de la API. De esta forma, incluso si fallan todos los nodos maestros, aún se podrían mostrar las solicitudes de la API en los nodos de la aplicación principal para lograr alta disponibilidad.

Cuando se inicia un nodo de la aplicación principal, se ejecuta como aplicación principal secundaria hasta que el nodo maestro primario la promueve a aplicación principal primaria para conectarse con el servidor de WhatsApp. Después de eso, es responsable de manejar las solicitudes de la API.

Supervisión basada en base de datos

Cada nodo de la aplicación principal actualizará la base de datos a cada minuto para mostrarse activo. El nodo maestro primario verificará periódicamente la base de datos para detectar nodos de la aplicación principal no saludables. Si un nodo de la aplicación principal primaria no actualizó la base de datos por más de dos minutos, el nodo maestro primario considerará que no es saludable y promoverá al lugar de primarios a otros nodos de la aplicación principal. De esta manera, el tiempo de inactividad será de aproximadamente dos minutos.

Supervisión basada en latidos

Si en un clúster se ejecuta más de un nodo maestro, la supervisión basada en latidos detecta las fallas de los nodos más rápidamente que la supervisión basada en base de datos. En la supervisión basada en latidos, todos los nodos maestros son responsables de supervisar a los nodos de la aplicación principal enviándoles latidos cada cinco segundos (se configura en heartbeat_interval). Si una aplicación principal primaria no le respondió al nodo maestro primario y a un nodo maestro secundario durante 30 segundos (se configura en unhealthy_interval), se considera no saludable. En este caso, el nodo maestro primario promoverá una aplicación principal secundaria saludable a aplicación principal primaria. De esta manera, y de forma predeterminada, el tiempo de inactividad será de aproximadamente 30 segundos. Si prefieres un tiempo de inactividad menor, puedes reducir el valor unhealthy_interval. Consulta la documentación sobre configuración para obtener ejemplos de cargas.

Configuración inicial

En un clúster de alta disponibilidad, hay tres tipos de nodos: app web, maestro y app principal. Pueden iniciarse por separado en diferentes máquinas, pero deben estar en la misma red para que se puedan comunicar entre sí.

Un nodo de app web es responsable de tratar el tráfico de la API como el contenedor de app web original. Un nodo de aplicación principal es responsable de manejar el tráfico de mensajes hacia y desde WhatsApp. Por último, un nodo maestro es responsable de supervisar nodos de aplicación principal en el clúster, de modo que si un nodo de aplicación principal queda inactivo, el tráfico se redirigirá a otro nodo de aplicación principal para proporcionar alta disponibilidad. Puede haber varios nodos de app web, nodos de app principal y nodos maestros en el clúster.

No se refieren más a los nodos activos como "nodos esclavos". Se los denomina "nodos de app principal".

Nota: En la mayoría de los casos, debe ejecutarse la base de datos en un servidor físico separado de los contenedores de la aplicación principal y de la aplicación web para los entornos de producción. Para lograr una alta disponibilidad real, se recomienda ejecutar los contenedores maestros, de app web y de app principal en diferentes máquinas físicas.

Configurar un sistema de archivos compartido para mensajes multimedia

Si no te interesan los mensajes con contenido multimedia, omite este paso.

Con el fin de lograr la compatibilidad de enviar y recibir mensajes con contenido multimedia, es necesario configurar un sistema de archivos NFS y montarlo en un directorio local en todos los nodos de app web, maestros y de app principal. Asegúrate de que se hayan otorgado permisos de lectura y escritura en el directorio compartido.

Ejemplo de un comando de montaje de NFS:

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

Instalación con Docker Compose

Para usar esta guía, debes tener Docker, una plataforma de contenedor que permite ejecutar el cliente de la API de WhatsApp Business. También debes tener Docker Compose. Docker Compose ya viene incorporado en Docker para macOS y Windows, pero debe instalarse por separado en Linux.

Configuración de desarrollador con un solo servidor

  1. Instala Docker en tu sistema.
  2. Si Docker Compose no está incorporado en Docker, instálalo.
  3. Descarga los archivos de configuración multiconnect-compose.yml y db.env: Archivos_de_configuración_de_WhatsApp.zip.
  4. Abre una consola y ve al directorio donde guardaste los archivos descargados.
  5. Si estás ejecutando una instalación de MySQL, cambia los valores en el archivo db.env para que coincidan con tu configuración de MySQL. En caso contrario, los archivos multiconnect-compose.yml y db.env tienen una configuración predeterminada que genera una instancia en un contenedor local.
  6. Asegúrate de que no haya ningún contenedor solo ejecutándose antes de iniciar los múltiples contenedores para alta disponibilidad:
      docker-compose -f your-single-connect-yml-filename stop
    
  7. Ejecuta el siguiente comando en la consola:
    docker-compose -f multiconnect-compose.yml up
    Recibirás salidas mientras el script descargue las imágenes de Docker y configure todo. Para ejecutar los contenedores en segundo plano, utiliza el parámetro -d:
    docker-compose -f multiconnect-compose.yml up -d

Cuando hayas terminado, usa el siguiente comando para verificar que los contenedores estén funcionando:

docker-compose ps

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

Configuración de la producción con servidores múltiples para cada contenedor

  1. Instala Docker en tus sistemas.
  2. Si Docker Compose no está incorporado en 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 y guárdalos en los servidores respectivos.
  4. En los servidores, abre una consola y ve al directorio donde guardaste los archivos descargados.
  5. En una configuración de producción, se recomienda que uses una instancia de MySQL independiente. Una vez que cuentes con una, cambia los valores en el archivo db.env para que coincidan con tu configuración de MySQL.
  6. Asegúrate de que no haya ningún contenedor solo ejecutándose antes de iniciar los múltiples contenedores para alta disponibilidad:
    docker-compose -f your-single-connect-yml-filename stop
    
  7. Ejecuta los siguientes comandos en la consola para cada una de las máquinas:

    La variable de entorno EXTERNAL_HOSTNAME debe ser una dirección IP o nombre de host que sea accesible desde las máquinas que ejecutan otros contenedores. Los puertos expuestos en un archivo YML de servicio deberían estar abiertos a las conexiones de las máquinas que ejecutan otros contenedores. Por ejemplo, los puertos definidos como COREAPP_EXTERNAL_PORTS en multiconnect-coreapp.yml requieren estar abiertos al tráfico de entrada en el host que ejecuta los contenedores 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
    Recibirás salidas mientras el script descargue las imágenes de Docker y configure 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

Cuando hayas terminado, usa el siguiente comando para verificar que los contenedores estén funcionando:

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

Si se ejecutan instancias múltiples del mismo servicio (por ejemplo, ejecutar 2 app principales en el mismo host), no funcionará de forma predeterminada porque existe un conflicto con el puerto del host. Para evitar este conflicto, es necesario que modifiques el archivo YML de servicio correspondiente, en este caso multiconnect-coreapp.yml, para exponer los diferentes puertos host para cada instancia como se muestra a continuación:

ports:
- "HOST_PORT_RANGE:6250-6253"

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

Actualización

Configuración de desarrollador con un solo servidor

El archivo multiconnect-compose.yml tiene campos que indican las versiones de los contenedores. 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 versiones del 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

Luego, reinicia los contenedores de Docker:

docker-compose -f multiconnect-compose.yml up

Configuración de la producción con servidores múltiples 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 versiones de 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

Luego, 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 de contenido multimedia de una instalación anterior, reemplaza la definición del siguiente volumen 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 si deseas mantener el volumen de montaje de enlace actual.

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

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

Desinstalación

Configuración de desarrollador con un solo servidor

Debes repetirlo para todas las máquinas en las que ejecutes nodos.

Si debes eliminar todos los contenedores para restablecer el entorno de desarrollo, ejecuta el siguiente comando desde el directorio que contiene el archivo multiconnect-compose.yml:

docker-compose -f multiconnect-compose.yml down

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

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

Configuración de la producción con servidores múltiples para cada contenedor

Si debes eliminar todos los contenedores para restablecer el entorno de desarrollo, 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

Si, además de los contenedores, quieres eliminar todos los volúmenes definidos en los archivos YAML, 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 para solución de problemas

Si deseas obtener registros para solucionar problemas, ejecuta el siguiente comando en los servidores:

  docker-compose logs > debug_output.txt