NGINX Plus 가 Zone 동기화를 수행하는 방법

NGINX STORE > Docs > NGINX Plus Documentation > NGINX Plus 가 Zone 동기화를 수행하는 방법
NGINX Plus

NGINX Plus 가 Zone 동기화를 수행하는 방법

NGINX Plus 클러스터에서 데이터를 동기화할 수 있는 Zone 동기화 기능의 설계 및 제한 사항에 대해 설명합니다.

목차

1. 소개
1-1. 사용 사례
2. Modules
3. 동기화
3-1. 데이터 모델
3-2. Data flow
4. 소개
4-1. Topology
4-2. 초기 상태

4-3. Wire Format
4-4. 모니터링
4-5. 스케일링
5. FAQ
6. History

1. 소개

1-1. 사용 사례

해당 기능의 특정 기능을 고려할 때, 즉 다음과 같습니다.

  • 다른 노드와 협의하지 않고 각 노드에서 요청을 개별적으로 처리합니다.
  • 최종 변경 사항 전달
  • 만료되는 레코드

다음과 같은 사용 사례가 고려됩니다.

  • 세션 캐싱: 첫 번째 요청이 다른 노드와 공유되는 세션을 생성합니다. 후속 요청은 모든 클러스터 노드에서 동일한 세션을 사용합니다. 노드에서 세션이 누락되는 것은 치명적인 오류라기보다는 성능 저하로 이어집니다.
  • 리소스 제한: 각 노드는 로컬 리소스를 평가하여 다른 노드에 알립니다. 평균적으로 클러스터 제한이 적절하게 적용됩니다.
  • 동적 구성: 동적 구성 항목(예: 임시 리다이렉션 규칙, 액세스 규칙 및 제한)은 한 노드에 입력된 후 클러스터 내에서 자동으로 공유됩니다. 다른 노드가 이를 수신하는 즉시 새 규칙이 적용됩니다.

2. Modules

이 기능은 복잡하며 NGINX core, ngx_stream_zone_sync_module 모듈, 공유 Zone을 실제로 사용하는 모듈(예: sticky 또는 limit_req 모듈; 여기서는 이러한 모듈을 functional 모듈이라고 부름)로 나뉘어 지원됩니다.

  • 여기에서는 Zone 동기화 모듈이 담당합니다:
    • 클러스터 노드 검색
    • 클러스터 노드에 대한 네트워크 연결 관리
    • 전송 계층 보안 제공(SSL 모듈 사용)
    • 기능 모듈에서 제공하는 데이터를 원격 노드로 Push합니다.
    • 원격 노드로부터 데이터를 받아 기능 모듈로 전송합니다.
  • Zone의 변경 사항을 추적하고 Zone의 출력 Queue을 처리합니다.

서버 측에서 Zone 동기화 모듈은 일반 stream 모듈이므로 액세스 제어, 전송 계층 보안 및 제한이 지원됩니다.

기능 모듈은 다음을 담당합니다:

  • Key 및 Timestamp Metadata와 함께 네트워크를 통해 전송할 수 있도록 Zone 레코드를 직렬화합니다.
  • 메시지 역직렬화 및 원격 데이터로 로컬 Zone 업데이트
  • 로컬로 업데이트되어 클러스터 내에 배포해야 하는 레코드 Queue 유지 관리

Core는 Zone 동기화 모듈과 기능 모듈 간에 필요한 인터페이스를 제공합니다.

3. 동기화

3-1. 데이터 모델

각 기능 모듈은 해당 데이터를 레코드 Queue로 표현합니다. Zone 동기화 모듈의 경우 레코드는 불투명하며, 다른 노드로 레코드를 전송하는 동안 레코드의 직렬화된 표현만 처리합니다. Queue에는 클러스터로 보내야 하는 레코드가 포함되어 있습니다. 노드에서 로컬로 생성된 레코드만 출력 Queue에 표시될 수 있습니다. Queue는 포괄적이며 Zone에 저장된 모든 레코드를 포함할 수 있습니다.

Zone 동기화 모듈은 구성된 Zone의 출력 Queue을 일정한 간격으로 Polling하여 클러스터의 불일치 구간을 제어합니다. 또한 단일 레코드를 자주 업데이트하는 경우(세션의 일반적인 사용 사례로, 세션이 생성된 후 나중에 여러 번 업데이트되는 경우) 전송되는 데이터의 양을 줄일 수 있습니다.

동기화된 레코드를 만들거나 업데이트할 수 있습니다. 현재 삭제 작업은 지원되지 않으며, 대신 각 레코드에는 구성에 정의된 수명이 있습니다. 레코드가 만료되면 로컬에서 삭제되며 클러스터로 업데이트가 전송되지 않습니다.

기능 모듈은 액세스/업데이트 시 기록 유효기간을 연장할지 여부를 제어합니다.

클러스터 노드 간에 업데이트된 값이 달라지는 시간 간격이 항상 존재하기 때문에 데이터는 결국 일관성을 유지하게 됩니다. Zone 동기화 간격을 조정하여 구간을 줄일 수는 있지만 제거할 수는 없습니다. CAP 정리의 관점에서 Zone 동기화 클러스터는 AP 시스템으로 분류할 수 있습니다.

일관성은 각 노드가 결국 클러스터에서 발생한 모든 이벤트를 타임스탬프 순으로 수신하고 공통 알고리즘을 사용하여 처리한 후 다른 노드와 동일한 상태에 도달한다는 사실에 의해 보장됩니다.

분명히 알고리즘은 모든 클러스터 노드의 적절한 시간 동기화에 따라 달라지므로 모든 노드에 NTP 또는 유사한 기술을 설정하는 것이 중요합니다.

3-2. Data flow

1. 기능 모듈은 새 레코드(예: 새 Sticky Session)를 만듭니다.

2. 레코드가 출력 Queue에 삽입됩니다.

3. 기능 모듈은 정상 작동을 계속할 수 있습니다. 따라서 레코드는 다른 노드와 공유되기 전에 여러 번 업데이트되거나 삭제될 수도 있습니다(예: 직접 요청 후 노드에서 로컬로 삭제).

4. 주기적인 타이머가 트리거되고 Zone 동기화 모듈이 기능 모듈의 출력 Queue룰 검사합니다.

5. Queue가 비어 있지 않으면 Zone 동기화 모듈은 기능 모듈에 나가는 레코드를 직렬화하도록 요청하고 자체 버퍼에 기록합니다.

6. 기능 모듈은 자체 직렬화 형식을 사용하여 레코드를 직렬화합니다. 일반적으로 Key, Timestamp, Payload가 포함됩니다.

7. Zone 동기화 모듈은 사용 가능한 버퍼 공간이 없거나 Queue가 비어 있을 때까지 출력 Queue을 소비합니다.

8. 마지막으로 Zone 동기화 모듈은 읽은 모든 정보를 연결을 설정한 노드로 전송하여 레코드를 Zone 이름 및 버전 세부 정보가 포함된 메시지로 구성합니다. 오류가 발생하여 노드에 레코드를 전달할 수 없는 경우, 노드에 대한 연결이 닫히고 다시 설정됩니다. 아래 클러스터의 초기 상태에 대한 설명을 참조하세요.

9. 원격 노드는 메시지를 수신하여 적절한 기능 모듈 및 Zone으로 메시지를 전송합니다. 이제 기능 모듈은 원격 노드의 정보( key, timestamp, payload)를 사용하여 로컬 상태를 다음과 같이 새로 고쳐야 합니다.

  • 해당 Key가 없는 경우 해당 Key에 새 레코드를 삽입합니다.
  • 원격 Timestamp가 더 최신인 경우 기존 레코드 업데이트하기
  • 로컬 Timestamp가 더 최신인 경우 업데이트 무시하기

10. Zone 상태를 디스크에 직렬화할 수 있는 기능 모듈(“상태”가 활성화된 keyval)은 레코드 타임스탬프를 저장하여 서버 재시작 후 레코드 수명을 적절히 처리할 수 있도록 합니다.

4. 소개

4-1. Topology

Topology적으로 클러스터는 각 노드가 다른 모든 노드에 연결되고 모든 변경 사항이 다른 노드로 Push되는 Full Mesh입니다.

모든 클러스터 노드는 동일합니다. 특별한 central 노드나 main 노드가 없으며, 각 노드는 다른 노드를 기다리지 않고 요청을 처리합니다.

노드는 변경 사항을 로컬 메모리에 Commit하고 요청을 계속 처리합니다. 다른 노드는 결국 로컬 변경 사항에 대해 알림을 받게 됩니다.

노드는 자신의 로컬 값이 “best/latest” 값인지 알지 못하며, 다른 노드의 업데이트가 적용될 때까지 해당 값에 의존합니다.

노드는 다른 노드의 변경 사항을 수신 대기하고 변경 사항이 도착하면 이를 적용합니다.

4-2. 초기 상태

노드가 클러스터에 연결되면 이미 상태를 가지고 있으며, 이 상태의 일부가 이전에 클러스터로 전송되었는지 여부는 알 수 없습니다. 궁극적인 해결책은 전체 노드 상태를 클러스터와 병합하는 것입니다. 이 프로세스를 스냅샷이라고 하며, 새 노드와 네트워크 연결이 설정되면 클러스터와 노드가 스냅샷을 교환합니다. 가장 최신 버전의 레코드가 선택되어 새로운 Joint 상태를 형성합니다. 이 프로세스는 일반 작업과 병렬로 실행되므로 노드는 스냅샷이 끝날 때까지 기다릴 필요가 없습니다.

클러스터 Brain 분할 후에도 동일한 프로세스가 발생합니다. 새 노드가 클러스터에 나타나고 현재 상태를 Peer와 교환합니다. 상태가 크고 클러스터에 노드가 많은 경우 동기화에 다소 시간이 걸리고 산발적으로 시스템 부하가 추가로 발생할 수 있습니다.

노드가 오프라인 상태가 되면 일시적으로 다른 노드에 영향을 미칩니다. 쓰기 제한 시간이 만료되거나 연결 쓰기 오류가 감지되면 Zone에서 다음 데이터 읽기가 지연되고 결함이 있는 노드의 연결이 끊어집니다. 그런 다음 오프라인 노드에 대한 연결이 다시 설정될 때까지 나머지 노드 간에 동기화가 계속됩니다.

4-3. Wire Format

모듈은 노드 연결별로 미리 할당된 버퍼 세트를 사용하여 변경 사항을 전달합니다. 버퍼에는 메시지 헤더와 직렬화된 레코드가 포함됩니다. 메시지 헤더에는 다음이 포함됩니다.

  • Payload를 포함한 전체 메시지 길이
  • 프로토콜 버전(현재 1)
  • Zone 이름 길이
  • 모듈 태그 – 고유 모듈 ID
  • 모듈 버전
  • 대상 Zone 이름

고정 길이 헤더 섹션의 크기는 12Byte입니다. 메시지가 성공적으로 발송되려면 서명(모듈 태그 및 버전)이 대상과 일치해야 합니다. 알 수 없는 서명이 있는 메시지는 무시됩니다(예: 다른 노드에 새 영역을 추가하면 이러한 메시지가 나올 수 있음). 직렬화된 레코드의 길이는 특정 기능 모듈에 따라 다릅니다. 예를 들어, 스티커 모듈은 21Byte의 고정 길이 헤더와 최대 32Byte의 세션 ID를 생성합니다. 직렬화된 단일 레코드가 너무 커서 버퍼에 맞지 않으면 오류가 기록되고 동기화 중에 해당 레코드가 무시됩니다. 이는 또한 버퍼 크기를 늘려야 함을 의미합니다.

4-4. 모니터링

액세스 로그의 표준 기능을 사용하면 다른 클러스터 노드와의 stream 세션을 관찰하고 $remote_addr, $status, $upstream_bytes_sent 또는 $bytes_received와 같은 지원되는 변수를 기록할 수 있습니다. 오류 로그에는 노드 검색, 노드 연결, 수락된 클라이언트 등 다양한 이벤트에 대한 세부 정보가 포함된 NOTICE 수준 항목이 등록됩니다. 발생하는 오류는 적절한 수준에서 보고됩니다.

Zone 동기화 모듈은 API 모듈을 통해 여러 카운터를 내보냅니다. stream/zone_sync Endpoint에는 인스턴스별 정보가 있는 상태 Endpoint가 포함되며, zone/ Endpoint에는 Zone별 통계가 나열됩니다.

노드 온라인 지표는 다른 노드에 설정된 연결 수를 표시합니다. 일반적으로 N에서 1을 뺀 값으로 예상되며, 여기서 N은 모든 클러스터 노드의 수입니다.

또한 Endpoint에는 Inbound 및 Outbound 메시지와 Byte의 누적 카운터가 포함되어 있습니다.

Zone 별 통계에는 공유 메모리 Zone의 총 레코드 수와 출력 Queue의 레코드 수가 포함됩니다.

4-5. 스케일링

동기화를 통해 노드는 다른 노드로부터 여러 업데이트를 받기 시작하며, 일반적으로 레코드를 삽입/업데이트하기 위해서는 일정량의 공유 메모리를 잠가야 합니다.

Worker와 노드가 많으면 병목 현상이 발생할 수 있습니다. 이벤트 수가 많으면 소비되는 네트워크 대역폭과 CPU 사용량도 그에 따라 증가합니다.

5. FAQ

Q. 노드가 클러스터에서 격리되면 어떻게 되나요?

A. 노드가 클러스터에서 격리되어 있어도 로컬에서 세션을 관리하고 클라이언트에 계속 응답하면서 다른 노드에 계속 연결을 시도하는 등 단일 노드로 계속 작동합니다.

Q. 격리된 노드가 클러스터에 다시 연결되면 어떻게 되나요?

A. 노드가 다시 연결되면 모든 로컬 세션을 클러스터로 보내고 다른 노드로부터 데이터를 수신하는 전체 재동기화를 수행하므로 모든 노드가 연결되면 결국 일관된 상태에 도달하게 됩니다.

Q. 여러 노드가 동일한 데이터로 동기화되는 경우 충돌은 어떻게 해결되나요?

A. 충돌 해결은 시간을 기준으로 이루어지므로 클러스터 전체에서 시계를 동기화하는 것이 중요합니다. 두 노드가 동일한 Key로 레코드를 생성한 경우 최신 레코드가 승리합니다.

Q. 클러스터 동기화 데이터에 대한 상태 파일이 있나요?

A. 아니요. 클러스터 동기화 데이터는 클러스터 전체에서 공유되므로 디스크에 기록할 필요가 없습니다. keyval 모듈은 로컬 노드 상태를 디스크에 저장할 수 있습니다.

Q. 동기화가 완료되기 전에 연결을 거부하도록 NGINX Plus를 구성할 수 있나요?

A. 아니요, 그런 상태는 존재하지 않습니다. 각 노드는 다른 노드로부터 업데이트 Stream을 수신하고 자신의 업데이트를 다른 노드로 전송할 뿐입니다. 클러스터에 새로운 데이터가 도착하지 않으면 모든 노드에 백로그 Queue이 비어 있고 이를 ‘동기화 완료’로 간주할 수 있지만, 실제로는 항상 클라이언트가 있기 때문에 이러한 상황은 일반적으로 발생하지 않습니다.

Q. 노드를 의도적으로 오프라인으로 전환하려면 어떻게 해야 하나요?

A. 이 문서에서는 클러스터 노드를 제어하는 방법을 설명합니다.

Q. 클러스터 상태 데이터를 모니터링하려면 어떻게 해야 하나요?

A. NGINX Plus API에서 동기화된 각 영역에 대해 2개의 카운터를 사용할 수 있습니다: 노드의 총 레코드 수와 전송해야 하는 레코드 수입니다. 모든 노드의 레코드 수가 거의 같고 발신 Queue이 거의 비어 있으면 클러스터가 정상으로 간주할 수 있습니다.

Q. 클러스터 상태를 모니터링하려면 어떻게 해야 하나요?

A. NGINX Plus API가 추가로 노출하는 지표는 두 가지입니다.

  1. 연결된 노드 수: 모든 노드에서 동일해야 하며 클러스터의 총 노드 수에서 1을 뺀 값과 같아야 합니다. 즉, 클러스터 연결을 모니터링할 수 있습니다. 일부 노드가 죽거나 연결이 끊어지면 이 카운터가 변경됩니다.
  2. Send Queue 길이: 이상적으로는 0(낮은 부하) 또는 일정한 수(평균 부하)입니다. 백로그가 증가하고 있는데 클러스터에 노드를 추가하거나 제거하는 등의 변경을 하지 않았다면 문제(네트워크 연결 문제, 죽은 노드 등)가 있음을 나타냅니다.
  3. 평소와 같이 오류 로그 모니터링: 모든 관련 이벤트가 기록됩니다. 기본적으로 오류만 기록됩니다. 정보 수준에서 더 많은 클러스터 이벤트를 볼 수 있습니다.

6. History

NGINX Plus R15에서는 인스턴스 간 메모리 Zone을 동기화하는 기능이 도입되었으며, 현재는 학습 방식의 Sticky Session만 지원되었습니다.

NGINX Plus R16에서는 공유 Zone 동기화가 확장되어 keyval 및 limit_req 모듈을 지원합니다.

NGINX Plus R18에서는 listen 지시문의 와일드카드를 사용하여 클러스터의 모든 인스턴스 간에 단일 zone_sync 구성을 적용할 수 있습니다.