Configurar alta disponibilidade

A solução-padrão do cliente da WhatsApp Business API é executada em um único contêiner do Docker. Se vários contêineres do Docker ficarem em execução, isso causará problemas e resultará no banimento temporário da sua conta. Este guia explicará como configurar a alta disponibilidade, permitindo que você deixe os contêineres do Docker em modo de espera caso o contêiner principal do Docker pare de funcionar.

Esta solução de alta disponibilidade exige que uma instalação existente de instância única do cliente da WhatsApp Business API seja executada sobre ela. Caso ainda não tenha configurado o número de telefone do cliente da WhatsApp Business API, consulte a documentação de instalação antes de continuar.

Visão geral

Um cluster de alta disponibilidade requer pelo menos dois nós Master e dois nós Coreapp, como mostrado no diagrama a seguir:

Cluster de alta disponibilidade

Recomendamos que todos os nós sejam executados em diferentes máquinas/racks para evitar que falhas em uma máquina ou um rack afetem vários nós ao mesmo tempo.

Como começar

Quando um cluster é iniciado, todos os nós mestre competirão para obter a concessão mestre a fim de se tornarem primários. Apenas um nó conseguirá, e os outros se tornarão mestres secundários. Se houver N nós Master no cluster, haverá um Master primário e N - 1 Masters secundários. O mestre primário é responsável pelas seguintes atividades: registro, atualização do esquema do banco de dados, transmissão das alterações na configuração, relatório das estatísticas do banco de dados, gerenciamento do cluster e assim por diante. Se o mestre primário expirar e perder a concessão mestre, outros m=mestres secundários competirão para assumir a posição de mestre primário.

Quando um mestre se tornar primário, ele carregará primeiro a tabela do mapa de fragmentos do banco de dados para saber qual é o Coreapp primário atual. Se não houver um Coreapp primário no cluster, o mestre primário promoverá um Coreapp secundário íntegro a essa posição e atualizará a tabela do mapa de fragmentos no banco de dados para que o Webapp possa procurar que nó Coreapp deve receber as solicitações da API. Dessa forma, mesmo se todos os mestres ficarem inativos, as solicitações da API ainda poderão ser atendidas nos nós Coreapp para obter alta disponibilidade.

Quando um nó Coreapp for iniciado, ele será executado como um Coreapp secundário até que o mestre primário o promova a Coreapp primário para conexão com o servidor do WhatsApp. Depois disso, ele será responsável por processar as solicitações da API.

Monitoramento baseado em banco de dados

Cada nó Coreapp atualizará o banco de dados a cada minuto para obter a atividade dele. O mestre primário verificará o banco de dados periodicamente para detectar nós Coreapp não íntegros. Se um nó Coreapp primário não atualizar o banco de dados por mais de 2 minutos, o mestre primário o considerará não íntegro e promoverá outros nós Coreapp a essa posição. Dessa maneira, o tempo de inatividade é de aproximadamente 2 minutos.

Monitoramento baseado em pulsação

Se um cluster tiver mais de um mestre em execução, o monitoramento baseado em pulsação detectará falhas de nó mais rápido do que o monitoramento baseado em banco de dados. No monitoramento baseado em pulsação, todos os Masters são responsáveis por monitorar os nós Coreapp pelo envio de pulsações a cada 5 segundos (configurado por heartbeat_interval). Caso um Coreapp primário não responda ao Master primário nem a um Master secundário por 30 segundos (configurado por unhealthy_interval), ele será considerado não íntegro, e o Master primário promoverá um Coreapp secundário íntegro a Coreapp primário. Dessa maneira, o tempo de inatividade é, por padrão, de aproximadamente 30 segundos. Você poderá diminuir o valor de unhealthy_interval se preferir um tempo de inatividade menor. Consulte a documentação sobre as configurações para ver exemplos de cargas.

Configuração inicial

Em um cluster de alta disponibilidade, há três tipos de nós: Webapp, Master e Coreapp. Eles podem ser iniciados separadamente em diferentes máquinas, mas devem ficar na mesma rede para que possam se comunicar entre si.

Um nó do Webapp é responsável por lidar com o tráfego da API como o contêiner original do Webapp. Um nó do Coreapp é responsável por lidar com o tráfego de mensagens de entrada e saída do WhatsApp. Por fim, um nó Principal é responsável por monitorar nós do Coreapp no cluster, então, se um nó ficar inativo, ele redirecionará o tráfego a outro para alta disponibilidade. Pode haver vários nós do Webapp, do Coreapp e do Master no cluster.

Nós ativos não são mais chamados de nós secundários. Eles são chamados de nós do Coreapp.

Observação: para ambientes de produção, na maioria dos casos, é necessário executar o banco de dados em um servidor físico separado dos contêineres do Coreapp e do Webapp. Para ter uma Alta Disponibilidade verdadeira, é recomendado executar os contêineres de Master, Webapp e Coreapp em diferentes máquinas físicas.

Configurar um sistema de arquivos compartilhado para mensagens de mídia

Se você não se importar com mensagens de mídia, ignore esta etapa.

Para dar suporte ao envio/recebimento de mensagens de mídia, é necessário configurar um sistema de arquivos NFS e montá-lo em um diretório local em todos os nós do Webapp, Coreapp e Master. Verifique se permissões de gravação/leitura foram concedidas no diretório compartilhado.

Exemplo de um comando de configuração do NFS:

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

Instalação com o Docker Compose

Este guia exige o uso do Docker, uma plataforma de contêineres que permite a execução do cliente da WhatsApp Business API. O Docker Compose também é necessário. O Docker Compose acompanha o Docker para macOS e Windows, mas precisa de uma instalação separada no Linux.

Configuração de desenvolvedor com um único servidor

  1. Instale o Docker no seu sistema.
  2. Se o Docker Compose não acompanhar a instalação do seu Docker, instale-o.
  3. Baixe os arquivos de configuração multiconnect-compose.yml e db.env: WhatsApp_Configuration_Files.zip.
  4. Abra um console e navegue até o diretório em que você salvou os arquivos baixados.
  5. Se você tiver uma instalação do MySQL em execução, altere os valores no arquivo db.env para que reflitam a sua configuração do MySQL. Se você não tiver o MySQL instalado, os arquivos multiconnect-compose.yml e db.env terão uma configuração-padrão para abrir uma instância em um contêiner local.
  6. Verifique se não há contêineres de conexão unificada sendo executados antes de iniciar múltiplos contêineres de alta disponibilidade:
      docker-compose -f your-single-connect-yml-filename stop
    
  7. Execute o seguinte comando no console:
    docker-compose -f multiconnect-compose.yml up
    Você receberá uma saída enquanto o script baixa as imagens do Docker e faz todas as configurações. Para executar os contêineres em plano de fundo, use o parâmetro -d:
    docker-compose -f multiconnect-compose.yml up -d

Assim que tiver concluído essas etapas, verifique se os contêineres estão em execução com o seguinte comando:

docker-compose ps

Por padrão, o contêiner do Webapp estará em execução na porta 9090.

Configuração de produção com vários servidores para cada contêiner

  1. Instale o Docker nos seus sistemas.
  2. Se o Docker Compose não acompanhar as instalações do seu Docker, instale-o.
  3. Baixe os arquivos de configuração multiconnect-coreapp.yml, multiconnect-master.yml, multiconnect-webapp.yml e db.env: WhatsApp_Configuration_Files.zip. Depois, salve cada um deles no respectivo servidor.
  4. Em cada servidor, abra um console e navegue até o diretório em que você salvou os arquivos baixados.
  5. Em uma configuração de produção, é recomendado que você use uma instância independente do MySQL. Assim que você tiver uma, altere os valores no arquivo db.env para que reflita as configurações do MySQL.
  6. Verifique se não há contêineres de conexão unificada sendo executados antes de iniciar múltiplos contêineres de alta disponibilidade:
    docker-compose -f your-single-connect-yml-filename stop
    
  7. Execute os seguintes comandos no console para cada respectiva máquina:

    A variável de ambiente EXTERNAL_HOSTNAME deve ser um endereço IP ou nome de host que seja acessível das máquinas que executam outros contêineres. As portas expostas em um arquivo YML de serviço precisam estar abertas a conexões de máquinas que executam outros contêineres. Por exemplo, as portas definidas como COREAPP_EXTERNAL_PORTS no multiconnect-coreapp.yml precisam estar abertas ao tráfego de entrada no host que executa contêineres 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
    Você receberá uma saída enquanto o script baixa as imagens do Docker e faz todas as configurações. Para executar os contêineres em plano de fundo, use o 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

Assim que tiver concluído essas etapas, verifique se os contêineres estão em execução com o seguinte comando:

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

Por padrão, a execução de várias instâncias do mesmo serviço (por exemplo, executar 2 Coreapps no mesmo host) não funcionará devido a conflitos de porta de host. Para evitar o conflito de portas, é necessário modificar o respectivo arquivo YML de serviço (neste caso, o multiconnect-coreapp.yml) a fim de expor diferentes portas de host para cada instância, conforme a seguir:

ports:
- "HOST_PORT_RANGE:6250-6253"

Por padrão, o contêiner do Webapp estará em execução na porta 9090.

Atualização

Configuração de desenvolvedor com um único servidor

O arquivo multiconnect-compose.yml tem campos que indicam as versões de contêiner. Por exemplo:

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 atualizar uma instalação, altere os números da versão no arquivo 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

Depois, reinicie os contêineres do Docker:

docker-compose -f multiconnect-compose.yml up

Configuração de produção com vários servidores para cada contêiner

Os arquivos YAML têm campos que indicam as versões dos contêineres. Por exemplo:

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 atualizar uma instalação, altere os números da versão nos respectivos arquivos:

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

Depois, reinicie os contêineres do 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

Como anexar volumes existentes

Se você tiver volumes de mídia de uma instalação anterior, substitua a definição de volume a seguir nos arquivos YAML:

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

por:

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

Montagens de vinculação

Essa ação será recomendada apenas se você quiser manter o volume de montagem de vinculação atual.

Caso queira configurar diretamente um caminho de host (uma localização existente no seu host) no contêiner, altere a linha de volume dentro da seção de serviço para que aponte para o caminho de host.

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

Desinstalação

Configuração de desenvolvedor com um único servidor

Você precisará repetir isso para todas as máquinas onde há nós em execução.

Se precisar redefinir o ambiente de desenvolvimento removendo todos os contêineres, execute o seguinte comando no diretório que contém o arquivo multiconnect-compose.yml:

docker-compose -f multiconnect-compose.yml down

Para eliminar todos os volumes definidos no arquivo multiconnect-compose.yml, além dos contêineres, execute down com o parâmetro -v:

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

Configuração de produção com vários servidores para cada contêiner

Se precisar redefinir o ambiente de desenvolvimento removendo todos os contêineres, execute o seguinte comando no diretório que contém o arquivo YAML em 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 eliminar todos os volumes definidos nos arquivos YAML, além dos contêineres, execute down com o 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 da solução de problemas

Para obter os registros de solução de problemas, execute o seguinte comando nos seus servidores:

  docker-compose logs > debug_output.txt