Настройка высокой доступности

Стандартный клиент WhatsApp Business API работает в одном контейнере Docker. Использование нескольких контейнеров Docker приведет к проблемам и временному запрету доступа для вашего аккаунта. Из этого руководства вы узнаете, как повысить доступность системы, создав резервные контейнеры Docker на случай отказа основного.

Для этого решения требуется конфигурация с одним экземпляром клиента WhatsApp Business API. Если вы ещё не настроили номер телефона для клиента WhatsApp Business API, сначала ознакомьтесь с документацией по установке.

Обзор

Для кластера повышенной доступности требуются по крайней мере два основных узла и два узла Coreapp, как показано на схеме:

Кластер повышенной доступности

Чтобы сбой оборудования не привел к отказу всего кластера, рекомендуем использовать для каждого узла отдельный компьютер или сервер.

Запуск

При запуске кластера определяется, какой из основных узлов станет главным. После этого остальные основные узлы считаются второстепенными. Таким образом, если в кластере N основных узлов, то среди них будет один главный и N – 1 второстепенных. Главный узел отвечает за регистрацию, обновление схемы базы данных, сбор статистики по БД, управление кластером, применение изменений в конфигурации к остальным узлам и т. п. Если главный узел выйдет из строя и потеряет контроль над кластером, за эту роль будут соревноваться остальные основные узлы.

Основной узел, ставший главным, в первую очередь загружает из базы данных таблицу сегментирования, чтобы определить главный узел Coreapp. Если в кластере его нет, главный узел назначает его, выбирая один из работоспособных узлов Coreapp, и обновляет таблицу сегментирования, чтобы та указывала узлу Webapp, на какой узел Coreapp отправлять запросы к API. При такой схеме кластер способен обрабатывать запросы к API на узлах Coreapp, даже если все основные узлы откажут.

После запуска каждый узел Coreapp считается второстепенным, пока главный основной узел не назначит его главным для подключения к серверу WhatsApp. С этого момента главный узел Coreapp отвечает за обработку запросов к API.

Мониторинг на основе базы данных

Каждый узел Coreapp ежеминутно связывается с базой данных, подтверждая свою работоспособность. Главный основной узел периодически проверяет базу данных, что позволяет выявлять неработоспособные узлы Coreapp. Если от главного узла Coreapp больше 2 минут не поступало сведений в базу данных, главный основной узел считает его неработоспособным и назначает новый главный узел Coreapp. Таким образом, максимальное время простоя составляет около 2 минут.

Мониторинг на основе контрольных сигналов

Если в кластере больше одного активного основного узла, мониторинг на основе контрольных сигналов позволяет распознавать нерабочие узлы быстрее, чем мониторинг на основе базы данных. При таком подходе все основные узлы отслеживают работоспособность узлов Coreapp, посылая им контрольные сигналы каждые 5 секунд (периодичность сигналов можно задать в поле heartbeat_interval). Если главный узел Coreapp в течение 30 секунд (значение в поле unhealthy_interval) не отвечает основным узлам (главному и одному из второстепенных), он считается неработоспособным, и главный основной узел назначает новый главный узел Coreapp. В этом случае максимальное время простоя по умолчанию составляет около 30 секунд. При желании значение unhealthy_interval можно уменьшить. Примеры полезных данных см. в разделе Настройки.

Начальная настройка

В кластере повышенной доступности имеется три типа узлов: Webapp, Coreapp и основные. Они могут работать на разных устройствах, но должны находиться в одной сети, чтобы взаимодействовать друг с другом.

Узел Webapp, как и контейнер Webapp, отвечает за обработку трафика API. Узел Coreapp отвечает за обработку трафика сообщений WhatsApp. Основной узел отвечает за мониторинг узлов Coreapp в кластере: в случае отказа одного из них он перенаправляет трафик на другой узел для обеспечения доступности. В кластере может быть несколько узлов Webapp, Coreapp и основных узлов.

Активные узлы больше не называются подчиненными. Теперь это узлы Coreapp.

Примечание. Для рабочих сред в большинстве случаев база данных должна работать на отдельном физическом сервере (не на том, где размещены контейнеры Coreapp и Webapp). Чтобы обеспечить настоящую повышенную доступность, рекомендуется размещать основные контейнеры, контейнеры Webapp и Coreapp на разных физических устройствах.

Настройка общей файловой системы для мультимедийных сообщений

Если вы не используете мультимедийные сообщения, пропустите этот шаг.

Для отправки и получения мультимедийных сообщений необходимо настроить файловую систему NFS и подключить ее к локальному каталогу на всех узлах Webapp, Coreapp и основных узлах. Не забудьте предоставить разрешения на чтение из общего каталога и запись в него.

Пример команды для подключения NFS:

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

Установка с помощью Docker Compose

Для выполнения действий, описанных в этом руководстве, потребуется Docker — платформа управления контейнерами, которая позволяет запускать клиент WhatsApp Business API. Кроме того, потребуется Docker Compose. Docker Compose входит в состав Docker для macOS и Windows. В Linux он устанавливается отдельно.

Конфигурация для разработки с одним сервером

  1. Установите Docker в своей системе.
  2. Если при этом не был развернут компонент Docker Compose, установите его.
  3. Скачайте файлы конфигурации multiconnect-compose.yml и db.env: WhatsApp_Configuration_Files.zip.
  4. Откройте консоль и перейдите в каталог, где сохранены скачанные файлы.
  5. Если у вас запущен экземпляр MySQL, измените значения в файле db.env в соответствии с конфигурацией MySQL. Если MySQL не установлен, файлы multiconnect-compose.yml и db.env содержат конфигурацию по умолчанию для развертывания экземпляра в локальном контейнере.
  6. Прежде чем запускать несколько контейнеров в конфигурации высокой доступности, убедитесь, что не запущен ни один контейнер с одним подключением:
      docker-compose -f your-single-connect-yml-filename stop
    
  7. Выполните в консоли следующую команду:
    docker-compose -f multiconnect-compose.yml up
    Во время скачивания скриптом образов Docker и настройки конфигурации в консоль выводятся некоторые данные. Для запуска контейнеров в фоновом режиме используйте параметр -d:
    docker-compose -f multiconnect-compose.yml up -d

Выполнив эти действия, убедитесь, что контейнеры запущены. Для этого выполните следующую команду:

docker-compose ps

По умолчанию контейнер Webapp работает через порт 9090.

Рабочая конфигурация с отдельными серверами для каждого контейнера

  1. Установите Docker в своих системах.
  2. Если при этом не был развернут компонент Docker Compose, установите его.
  3. Скачайте файлы конфигурации multiconnect-coreapp.yml, multiconnect-master.yml, multiconnect-webapp.yml и db.env: WhatsApp_Configuration_Files.zip. Сохраните их на соответствующих серверах.
  4. На каждом сервере откройте консоль и перейдите в каталог, где сохранены скачанные файлы.
  5. В рабочей конфигурации настоятельно рекомендуется использовать отдельный экземпляр MySQL. Создав его, измените значения в файле db.env в соответствии с конфигурацией MySQL.
  6. Прежде чем запускать несколько контейнеров в конфигурации высокой доступности, убедитесь, что не запущен ни один контейнер с одним подключением:
    docker-compose -f your-single-connect-yml-filename stop
    
  7. Выполните соответствующую команду в консоли для каждого устройства:

    В переменной среды EXTERNAL_HOSTNAME должен быть указан IP-адрес или имя хоста, доступные с устройств с другими контейнерами. Кроме того, для подключений с этих устройств порты, указанные в YML-файле сервиса, должны быть открыты. Например, порты, указанные как COREAPP_EXTERNAL_PORTS в multiconnect-coreapp.yml, должны быть открыты для входящего трафика на хосте, на котором запущены контейнеры 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
    Пока скрипт скачивает образы Docker и выполняется настройка конфигурации, в консоль выводятся некоторые данные. Для запуска контейнеров в фоновом режиме используйте параметр -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

После этого убедитесь, что контейнеры запущены. Для этого выполните следующую команду:

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

По умолчанию запустить несколько экземпляров одного сервиса (например, два экземпляра Coreapp на одном хосте) не получится из-за конфликта портов. Чтобы его избежать, необходимо внести изменения в соответствующий YML-файл сервиса (в данном случае это файл multiconnect-coreapp.yml) и открыть для каждого экземпляра свой набор портов на хосте:

ports:
- "HOST_PORT_RANGE:6250-6253"

По умолчанию контейнер Webapp работает через порт 9090.

Обновление

Конфигурация для разработки с одним сервером

В файле multiconnect-compose.yml есть поля, в которых указаны версии контейнеров. Пример:

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

Чтобы обновить установленный экземпляр, измените номера версий в файле 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

После этого перезапустите контейнеры Docker:

docker-compose -f multiconnect-compose.yml up

Рабочая конфигурация с отдельными серверами для каждого контейнера

В файлах YAML есть поля, в которых указаны версии контейнеров. Пример:

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

Чтобы обновить установленные экземпляры, измените номера версий в соответствующих файлах:

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

После этого перезапустите контейнеры 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

Прикрепление существующих томов

Если у вас остались тома медиаданных из ранее установленного экземпляра, замените следующее определение тома в файлах YAML:

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

Вместо него следует подставить:

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

Монтирование связей

Это необходимо, только если вы хотите сохранить существующий том с монтированием связей.

Чтобы непосредственно подключить путь (существующую папку) на хосте к контейнеру, укажите этот путь в строке тома в разделе сервиса.

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

Удаление

Конфигурация для разработки с одним сервером

Эти действия необходимо повторить для всех устройств, на которых работают узлы.

Чтобы сбросить среду разработки и удалить все контейнеры, выполните следующую команду из каталога, в котором находится файл multiconnect-compose.yml:

docker-compose -f multiconnect-compose.yml down

Чтобы помимо контейнеров удалить и все тома, определенные в файле multiconnect-compose.yml, выполните команду down с параметром -v:

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

Рабочая конфигурация с отдельными серверами для каждого контейнера

Чтобы сбросить среду разработки и удалить все контейнеры, выполните следующую команду из каталога, в котором находится файл YAML, на каждом сервере:

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

Чтобы помимо контейнеров удалить и все тома, определенные в файлах YAML, выполните команду down с параметром -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

Журналы для устранения неполадок

Чтобы сформировать журналы для устранения неполадок, выполните на серверах следующую команду:

  docker-compose logs > debug_output.txt