Стандартный клиент 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 и основных узлах. Не забудьте предоставить разрешения на чтение из общего каталога и запись в него.
mkdir new-local-directory mount -t nfs nfs_server_IP_addr:/share_directory new-local-directory
Для выполнения действий, описанных в этом руководстве, потребуется Docker — платформа управления контейнерами, которая позволяет запускать клиент WhatsApp Business API. Кроме того, потребуется Docker Compose. Docker Compose входит в состав Docker для macOS и Windows. В Linux он устанавливается отдельно.
multiconnect-compose.yml
и db.env
: WhatsApp_Configuration_Files.zip.
db.env
в соответствии с конфигурацией MySQL. Если MySQL не установлен, файлы multiconnect-compose.yml
и db.env
содержат конфигурацию по умолчанию для развертывания экземпляра в локальном контейнере.docker-compose -f your-single-connect-yml-filename stop
docker-compose -f multiconnect-compose.yml upВо время скачивания скриптом образов Docker и настройки конфигурации в консоль выводятся некоторые данные. Для запуска контейнеров в фоновом режиме используйте параметр
-d
:
docker-compose -f multiconnect-compose.yml up -d
Выполнив эти действия, убедитесь, что контейнеры запущены. Для этого выполните следующую команду:
docker-compose ps
По умолчанию контейнер Webapp работает через порт 9090.
multiconnect-coreapp.yml
, multiconnect-master.yml
, multiconnect-webapp.yml
и db.env
: WhatsApp_Configuration_Files.zip. Сохраните их на соответствующих серверах.
db.env
в соответствии с конфигурацией MySQL.docker-compose -f your-single-connect-yml-filename stop
В переменной среды 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