고가용성 설정

표준 WhatsApp Business API 클라이언트 솔루션은 단일 Docker 컨테이너에서 실행됩니다. 여러 Docker 컨테이너를 실행하면 문제가 발생하고 계정이 일시적으로 금지됩니다. 이 가이드에서는 고가용성 설정 방법을 자세히 설명하여 기본 Docker 컨테이너가 작동 중단되었을 경우에 대비해 Docker 컨테이너를 준비할 수 있도록 합니다.

이 고가용성 솔루션은 기존 WhatsApp Business API 클라이언트 싱글 인스턴스 설치본을 추가로 실행해야 합니다. 아직 WhatsApp Business API 클라이언트 전화번호를 설정하지 않았다면 이 솔루션을 사용하기 전에 설치 문서를 검토하세요.

개요

고가용성 클러스터는 아래의 다이어그램과 같이 Master 노드 2개, Coreapp 노드 2개 이상이 필요합니다.

고가용성 클러스터

모든 노드는 하나의 컴퓨터/랙에 고장이 발생해 여러 노드에 동시에 영향을 미치지 않도록 서로 다른 컴퓨터/랙에서 실행하는 것이 좋습니다.

시작

클러스터가 시작되면 모든 Master 노드가 마스터 리스를 잡아서 기본 Master가 되기 위해 경쟁합니다. 그중 한 개 노드만 성공하고 나머지는 보조 Master가 됩니다. 클러스터에 N개의 Master 노드가 있을 경우 기본 Master 1개와 N-1개 보조 Master가 있습니다. 기본 Master는 등록, 데이터베이스 스키마 업그레이드, 구성 변경 브로드캐스트, 보고, 데이터베이스 통계, 클러스터 관리 등을 담당합니다. 기본 Master가 죽어서 마스터 리스가 사라질 경우 다른 보조 m=Master가 기본 Master 자리를 두고 경쟁하게 됩니다.

기본 Master가 되면 먼저 데이터베이스에서 샤드 맵 테이블을 읽어들여 현재 기본 Coreapp이 누구인지부터 확인합니다. 클러스터에 기본 Coreapp이 없을 경우 기본 Master는 정상 상태의 보조 Coreapp을 기본 Coreapp으로 승격하고 데이터베이스에서 샤드 맵 테이블을 업데이트하여 Webapp이 API 요청을 보낼 Coreapp 노드를 조회할 수 있도록 합니다. 이렇게 하면 모든 Master가 정지하더라도 여전히 Coreapp 노드에서 API 요청을 처리하여 고가용성을 달성할 수 있습니다.

Coreapp 노드가 시작되면 보조 Coreapp으로 실행되다가, 기본 Master가 이를 기본 Coreapp으로 승격시키면 WhatsApp 서버와 연결됩니다. 그 이후에는 API 요청 처리를 담당하게 됩니다.

데이터베이스 기반 모니터링

각 Coreapp 노드는 1분마다 데이터베이스를 업데이트하여 생존(liveness)을 요청합니다. 기본 Master는 정기적으로 데이터베이스를 확인하여 비정상적인 Coreapp 노드를 감지합니다. 기본 Coreapp 노드가 데이터베이스를 2분 이상 업데이트하지 않으면 기본 Master는 이를 정상이 아닌 것으로 간주하고 다른 Coreapp을 기본 노드로 승격시킵니다. 이렇게 하면 가동 중단 시간이 약 2분이 됩니다.

박동 기반 모니터링

클러스터에 실행되는 Master가 2개 이상일 경우 박동 기반 모니터링이 데이터베이스 기반 모니터링보다 빠르게 노드 장애를 감지합니다. 박동 기반 모니터링에서는 모든 Master가 5초(heartbeat_interval로 구성)마다 박동을 보내 Coreapp 노드 모니터링을 담당합니다. 기본 Coreapp이 기본 Master와 보조 Master 1개에 30초(unhealthy_interval로 구성) 동안 응답하지 않으면 정상이 아닌 것으로 간주되어 기본 Master가 정상 보조 Coreapp을 기본 Coreapp으로 승격시킵니다. 이렇게 하면 기본적으로 가동 중단 시간이 약 30초가 됩니다. 가동 중단 시간을 더 단축하고 싶다면 unhealthy_interval 값을 낮출 수 있습니다. 예시 페이로드는 설정 문서를 참조하세요.

초기 설정

고가용성 클러스터에는 3가지 노드(Webapp, Master, Coreapp)가 있습니다. 이 노드는 다른 기기에서 따로 시작될 수 있으나 같은 네트워크상에 있어야 서로 통신할 수 있습니다.

Webapp 노드는 원본 Webapp 컨테이너 등의 API 트래픽을 처리합니다. Coreapp 노드는 WhatsApp으로 송수신되는 메시지 트래픽을 처리하는 작업을 담당합니다. 마지막으로 Master 노드는 클러스터에서 Coreapp 노드를 모니터링하는 작업을 담당합니다. Coreapp 노드 하나가 죽으면 다른 Coreapp 노드로 트래픽을 리디렉션하여 고가용성을 확보합니다. 클러스터에 여러 개의 Webapp 노드, Coreapp 노드, Master 노드가 있을 수 있습니다.

활성 노드는 더 이상 슬레이브 노드로 부르지 않고, Coreapp 노드라고 부릅니다.

참고: 프로덕션 환경에서는 대부분의 경우 데이터베이스를 Coreapp과 Webapp 컨테이너의 물리적 서버에서 별도로 실행해야 합니다. 진정한 고가용성을 구현하려면 여러 물리적 컴퓨터에서 Master, Webapp, Coreapp 컨테이너를 실행하는 것이 좋습니다.

미디어 메시지에 대한 공유된 파일 시스템 설정

미디어 메시지를 사용하지 않는다면 이 단계를 건너뛰세요.

미디어 메시지 전송/수신을 지원하려면 NFS 파일 시스템을 설정하고 모든 Webapp, Master, Coreapp 노드에서 로컬 디렉터리에 마운트하세요. 공유 디렉터리에는 읽기/쓰기 권한을 부여하세요.

NFS 마운트 명령 예시:

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

Docker Compose를 사용한 설치

이 가이드는 WhatsApp Business API 클라이언트를 실행할 수 있도록 하는 컨테이너 플랫폼인 Docker가 필요합니다. Docker Compose도 필요합니다. Docker Compose는 macOS 및 Windows용 Docker와 번들이지만 Linux에서는 별도의 설치가 필요합니다.

단일 서버를 사용한 개발자 설정

  1. 시스템에 Docker를 설치하세요.
  2. Docker Compose가 Docker 설치본과 함께 번들로 제공되지 않은 경우 설치하세요.
  3. multiconnect-compose.ymldb.env 구성 파일(WhatsApp_Configuration_Files.zip)을 다운로드하세요.
  4. 콘솔을 열고 다운로드한 파일을 저장한 디렉터리로 이동하세요.
  5. MySQL을 설치 중인 경우 db.env 파일의 값을 MySQL 구성에 맞게 변경하세요. MySQL이 설치되어 있지 않은 경우 docker-compose.ymldb.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가 Docker 설치본과 함께 번들로 제공되지 않은 경우 설치하세요.
  3. multiconnect-coreapp.yml, multiconnect-master.yml, multiconnect-webapp.ymldb.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 파일에 노출된 포트는 다른 컨테이너를 실행하는 컴퓨터의 연결에 대해 개방 상태여야 합니다. 예를 들어 multiconnect-coreapp.yml에서 COREAPP_EXTERNAL_PORTS로 정의된 포트는 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

기본적으로 같은 서비스에서 여러 인스턴스를 실행하면(예: 동일한 호스트에서 2개의 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

컨테이너와 함께 docker-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