브로커 로드 밸런싱 | 빠른 시작

브로커 로드 밸런싱 | 빠른 시작 (Broker load balancing | Quick start)

브로커 로드 밸런싱은 메시지를 브로커 전체에 고르게 분산해 Pulsar 클러스터 전반의 리소스를 효율적으로 활용하도록 도와줘요. 이 튜토리얼에서는 Docker에서 Pulsar 3.0.0을 사용해 브로커 로드 밸런싱을 시작하는 단계를 안내해요. 로드 밸런서를 자동으로 실행하는 방법과 수동으로 실행하는 방법을 모두 다루어요.

출처: 문서

본문

브로커 로드 밸런싱은 메시지를 브로커 전체에 고르게 분산하고 Pulsar 클러스터 전반의 리소스를 효율적으로 활용하도록 도와줘요.

이 튜토리얼은 Docker에서 Pulsar 3.0.0을 사용해 브로커 로드 밸런싱을 시작하는 단계를 안내해요.

사전 요구 사항 (Prerequisites)

  • Pulsar 설치:
    • modular 로드 밸런서를 실행하려면 Pulsar 1.7.0 이상 버전을 사용해요.
    • extensible 로드 밸런서를 실행하려면 Pulsar 3.0.0 이상 버전을 사용해요.
  • Docker 설치 및 최소 8GB 메모리 할당.

브로커 로드 밸런서를 자동으로 실행하도록 구성 (Configure broker load balancer to run automatically)

브로커 로드 밸런싱을 자동으로 사용하려면 다음 단계를 따라요.

1단계: ZooKeeper, bookie, broker 시작

docker-compose.yaml 파일을 만들고 다음 코드를 그 파일에 복사해요.

이 예시는 ZooKeeper 서버, bookie, 브로커 2개를 시작하고, 로드 밸런서 유형을 extensible로 설정하고, 언로드 전략을 TransferShedder로 설정하며, 디버그 모드를 활성화해요.

version: '3'
networks:
  pulsar:
    driver: bridge
services:
  # Start ZooKeeper
  zookeeper:
    image: apachepulsar/pulsar:latest
    container_name: zookeeper
    restart: on-failure
    networks:
      - pulsar
    volumes:
      - ./data/zookeeper:/pulsar/data/zookeeper
    environment:
      - metadataStoreUrl=zk:zookeeper:2181
      - PULSAR_MEM=-Xms256m -Xmx256m -XX:MaxDirectMemorySize=256m
    command: |
      bash -c "bin/apply-config-from-env.py conf/zookeeper.conf && \
             bin/generate-zookeeper-config.sh conf/zookeeper.conf && \
             exec bin/pulsar zookeeper"
    healthcheck:
      test: ["CMD", "bin/pulsar-zookeeper-ruok.sh"]
      interval: 10s
      timeout: 5s
      retries: 30

  # Initialize cluster metadata
  pulsar-init:
    container_name: pulsar-init
    hostname: pulsar-init
    image: apachepulsar/pulsar:latest
    networks:
      - pulsar
    command: |
      bin/pulsar initialize-cluster-metadata \
               --cluster cluster-a \
               --zookeeper zookeeper:2181 \
               --configuration-store zookeeper:2181 \
               --web-service-url http://broker:8080 \
               --broker-service-url pulsar://broker:6650
    depends_on:
      zookeeper:
        condition: service_healthy

  # Start bookie
  bookie:
    image: apachepulsar/pulsar:latest
    container_name: bookie
    restart: on-failure
    networks:
      - pulsar
    environment:
      - clusterName=cluster-a
      - zkServers=zookeeper:2181
      - metadataServiceUri=metadata-store:zk:zookeeper:2181
      - advertisedAddress=bookie
      - BOOKIE_MEM=-Xms512m -Xmx512m -XX:MaxDirectMemorySize=256m
    depends_on:
      zookeeper:
        condition: service_healthy
      pulsar-init:
        condition: service_completed_successfully
    volumes:
      - ./data/bookkeeper:/pulsar/data/bookkeeper
    command: bash -c "bin/apply-config-from-env.py conf/bookkeeper.conf && exec bin/pulsar bookie"

  # Start broker 1
  broker-1:
    image: apachepulsar/pulsar:latest
    container_name: broker-1
    hostname: broker-1
    restart: on-failure
    networks:
      - pulsar
    environment:
      - metadataStoreUrl=zk:zookeeper:2181
      - zookeeperServers=zookeeper:2181
      - clusterName=cluster-a
      - managedLedgerDefaultEnsembleSize=1
      - managedLedgerDefaultWriteQuorum=1
      - managedLedgerDefaultAckQuorum=1
      - advertisedAddress=broker-1
      - internalListenerName=internal
      - advertisedListeners=internal:pulsar://broker-1:6650
      - brokerServicePort=6650
      - webServicePort=8080
      - PULSAR_MEM=-Xms128m -Xmx2096m -XX:MaxDirectMemorySize=256m
      # Load Manager. Here uses the extensible load balancer, sets the unloading strategy to TransferShedder, and enables debug mode.
      - loadManagerClassName=org.apache.pulsar.broker.loadbalance.extensions.ExtensibleLoadManagerImpl
      - loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.extensions.scheduler.TransferShedder
      - PULSAR_PREFIX_loadBalancerDebugModeEnabled=true
    depends_on:
      zookeeper:
        condition: service_healthy
      bookie:
        condition: service_started
    command: bash -c "bin/apply-config-from-env.py conf/broker.conf && exec bin/pulsar broker"

  # Start broker 2
  broker-2:
    image: apachepulsar/pulsar:latest
    container_name: broker-2
    hostname: broker-2
    restart: on-failure
    networks:
      - pulsar
    environment:
      - metadataStoreUrl=zk:zookeeper:2181
      - zookeeperServers=zookeeper:2181
      - clusterName=cluster-a
      - managedLedgerDefaultEnsembleSize=1
      - managedLedgerDefaultWriteQuorum=1
      - managedLedgerDefaultAckQuorum=1
      - advertisedAddress=broker-2
      - internalListenerName=internal
      - advertisedListeners=internal:pulsar://broker-2:6650
      - webServicePort=8080
      - brokerServicePort=6650
      - PULSAR_MEM=-Xms128m -Xmx2096m -XX:MaxDirectMemorySize=256m
      # Load Manager. Here uses the extensible load balancer, sets the unloading strategy to TransferShedder, and enables debug mode.
      - loadManagerClassName=org.apache.pulsar.broker.loadbalance.extensions.ExtensibleLoadManagerImpl
      - loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.extensions.scheduler.TransferShedder
      - PULSAR_PREFIX_loadBalancerDebugModeEnabled=true

    depends_on:
      zookeeper:
        condition: service_healthy
      bookie:
        condition: service_started
    command: bash -c "bin/apply-config-from-env.py conf/broker.conf && exec bin/pulsar broker"

tip

위처럼 yaml 파일을 쓰는 대신 다른 방법을 쓴다면 broker.conf 파일에서 loadManagerClassName 또는 loadBalancerLoadSheddingStrategy를 업데이트해 브로커 로드 밸런서 유형을 고르거나 언로드 전략을 설정할 수 있어요.

Pulsar 버전과 언로드 전략이 호환되지 않으면 예외가 발생하므로 pulsar-admin update-dynamic-config는 사용하지 않는 게 좋아요.

2단계: Pulsar 클러스터 시작

2.1 터미널에서 탭을 하나 엽니다(즉 터미널 탭 1) 그리고 다음 명령을 실행해요.

2.2 Pulsar 클러스터를 시작해요.

입력:

docker compose up -d

출력:

출력은 브로커 1과 브로커 2가 실행 중임을 보여줘요.

[+] Running 12/12
 ✔ broker-1 Pulled                                                                                                                                                   242.5s
 ✔ zookeeper Pulled                                                                                                                                                  242.5s
 ✔ broker-2 Pulled                                                                                                                                                   242.5s
 ✔ pulsar-init Pulled                                                                                                                                                242.5s
 ✔ bookie 7 layers [⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                                  242.5s
   ✔ 3153aa388d02 Already exists                                                                                                                                       0.0s
   ✔ 5d127458ab3b Pull complete                                                                                                                                       83.3s
   ✔ 1f99067df50d Pull complete                                                                                                                                      160.0s
   ✔ 85fd7b6fa5dc Pull complete                                                                                                                                      160.0s
   ✔ ff6d7ec52b64 Pull complete                                                                                                                                      160.0s
   ✔ b53efccabef0 Pull complete                                                                                                                                      238.5s
   ✔ 6425449412d7 Pull complete                                                                                                                                      238.8s
[+] Running 11/11
 ✔ Network docker_pulsar                                                                                                                                      Created  0.1s
 ✔ Container zookeeper                                                                                                                                        Healthy 25.1s
 ! zookeeper The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested            0.0s
 ✔ Container pulsar-init                                                                                                                                      Exited  24.0s
 ! pulsar-init The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested          0.0s
 ✔ Container bookie                                                                                                                                           Started 24.2s
 ! bookie The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested               0.0s
 ✔ Container broker-1                                                                                                                                         Started 25.0s
 ✔ Container broker-2                                                                                                                                         Started 25.0s
 ! broker-1 The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested             0.0s
 ! broker-2 The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested             0.0s

3단계: 브로커와 로드 밸런서 상태 확인 (선택)

터미널 탭 1에서 다음 명령을 실행해요.

3.1 브로커 1의 컨테이너에 들어가요.

입력:

docker exec -it broker-1 bash

출력:

출력이 없으면 작업이 성공한 것이에요.

3.2 클러스터의 브로커 목록을 표시해요.

입력:

bin/pulsar-admin brokers list my-cluster

출력:

출력은 브로커가 2개임을 보여줘요.

broker-2:8081
broker-1:8080

3.3 로드 밸런서 유형을 확인해요.

입력:

bin/pulsar-admin brokers get-runtime-config | grep loadManagerClassName

출력:

출력은 로드 밸런서 유형이 extensible임을 보여줘요.

loadManagerClassName org.apache.pulsar.broker.loadbalance.extensions.ExtensibleLoadManagerImpl

4단계: 토픽 생성

터미널 탭 1에서 다음 명령을 실행해요.

4.1 브로커 1의 컨테이너에 들어가요.

입력:

docker exec -it broker-1 bash

출력:

출력이 없으면 작업이 성공한 것이에요.

4.2 my-tenant-1/my-namespace-1 아래에 2000개의 파티션을 가진 my-topic-1이라는 파티션 토픽을 생성해요.

tip

이 예시는 작업을 단순화하기 위해 번들을 1개만 지정해요. 합리적인 번들 수를 설정하는 방법은 Namespace bundles를 참고해요.

입력:

bin/pulsar-admin tenants create my-tenant-1
bin/pulsar-admin namespaces create my-tenant-1/my-namespace-1 --bundles 1
bin/pulsar-admin topics create-partitioned-topic persistent://my-tenant-1/my-namespace-1/my-topic-1 -p 2000

출력:

출력이 없으면 작업이 성공한 것이에요.

4.3 pulsar-perf 도구로 토픽에 메시지를 생산해요.

입력:

bin/pulsar-perf produce persistent://my-tenant-1/my-namespace-1/my-topic-1 -r 400 -bm 1 -mk random

출력:

출력은 메시지가 생산되었음을 보여줘요.

2023-07-21T05:08:24,261+0000 [main] INFO org.apache.pulsar.testclient.PerformanceProducer - JVM args [-Dlog4j.configurationFile=log4j2.yaml, -Djava.net.preferIPv4Stack=true, --add-opens=java.base/sun.net=ALL-UNNAMED, --add-opens=java.base/java.lang=ALL-UNNAMED, -Dpulsar.allocator.exit_on_oom=true, -Dio.netty.recycler.maxCapacityPerThread=4096, -Dpulsar.log.appender=Console, -Dpulsar.log.level=info, -Dpulsar.log.root.level=info, -Dpulsar.log.immediateFlush=false, -Dpulsar.log.dir=/pulsar/logs, -Dpulsar.log.file=pulsar-perftest.log]
2023-07-21T05:08:24,305+0000 [main] INFO org.apache.pulsar.testclient.PerformanceProducer - Netty max memory (PlatformDependent.maxDirectMemory()) 1 GB
2023-07-21T05:08:24,305+0000 [main] INFO org.apache.pulsar.testclient.PerformanceProducer - JVM max heap memory (Runtime.getRuntime().maxMemory()) 1 GB
2023-07-21T05:08:24,409+0000 [main] INFO org.apache.pulsar.testclient.PerformanceProducer - Starting Pulsar perf producer with config: {
...

5단계: 번들 분할

5.1 터미널에서 다른 탭을 엽니다(즉 터미널 탭 2) 그리고 다음 명령을 실행해요.

5.2 브로커 2의 컨테이너에 들어가요.

입력:

docker exec -it broker-2 bash

출력:

출력이 없으면 작업이 성공한 것이에요.

5.3 5분 후 번들이 분할되었는지 확인해요. Pulsar가 번들을 분할하는 데는 약간의 시간이 걸려요.

tip

  • 자동 번들 분할은 기본적으로 활성화돼 있어요. 비활성화하려면 broker.conf 파일에서 다음 구성을 false로 업데이트해요.

    loadBalancerAutoBundleSplitEnabled
    loadBalancerAutoUnloadSplitBundlesEnabled
    
  • 기본 번들 분할 알고리즘은 range_equally_divide예요. broker.conf 파일에서 defaultNamespaceBundleSplitAlgorithm을 업데이트해 다른 번들 분할 알고리즘으로 바꿀 수 있어요.

  • 번들 분할 임계값은 broker.conf 파일에서 더 많은 구성을 설정할 수 있어요. 임계값 중 하나라도 초과하는 기존 번들은 분할 후보가 돼요.

입력:

bin/pulsar-admin namespaces bundles my-tenant/my-namespace

출력:

출력은 번들이 3개의 범위로 분할되었음을 보여줘요.

{
  "boundaries" : [ "0x00000000", "0x3fffffff", "0x7fffffff", "0xffffffff" ],
  "numBundles" : 3
}

note

번들 수는 시간에 따라 달라질 수 있어요. 예를 들어 5분보다 오래 기다리면 번들 수가 늘어날 수 있어요. 번들 수가 2 이상이면 번들이 분할된 것이에요.

6단계: 번들 언로드

pulsar_lb_unload_bundle_total 메트릭으로 번들이 언로드되었는지 확인할 수 있어요. 이 방법은 자동 방식에서만 지원돼요.

tip

  • 자동 번들 언로드는 기본적으로 활성화돼 있어요. 비활성화하려면 broker.conf 파일에서 loadBalancerSheddingEnabled를 false로 업데이트해요.
  • 기본 번들 언로드 전략은 extensible 브로커 로드 밸런서의 경우 TransferShedder예요. modular 브로커 로드 밸런서의 경우 Pulsar 5.0.0부터 AvgShedder이고, 5.0.0-M1/M2와 Pulsar 2.10~4.x는 ThresholdShedder를 기본으로 해요. 구성·배치 요구 사항은 번들 언로드 전략을 참고해요. broker.conf 파일에서 loadBalancerLoadSheddingStrategy를 업데이트해 다른 번들 언로드 전략으로 바꿀 수 있어요.
  • 번들 언로드 조건은 broker.conf 파일에서 더 많은 구성을 설정할 수 있어요.

브로커 로드 밸런서를 수동으로 실행하도록 구성 (Configure broker load balancer to run manually)

브로커 로드 밸런싱을 수동으로 사용하려면 다음 단계를 따라요.

1단계: ZooKeeper, bookie, broker 시작

이는 자동 방식의 1단계(Start ZooKeeper, bookie, and broker)와 동일해요.

2단계: Pulsar 클러스터 시작

이는 자동 방식의 2단계(Start a Pulsar cluster)와 동일해요.

3단계: 토픽 생성

3.1 브로커 1의 컨테이너에 들어가요.

입력:

docker exec -it broker-1 bash

출력:

출력이 없으면 작업이 성공한 것이에요.

3.2 public/default 아래에 20개의 파티션을 가진 topic-manual이라는 파티션 토픽을 생성해요.

입력:

bin/pulsar-admin topics create-partitioned-topic persistent://public/default/topic-manual -p 20

출력:

출력이 없으면 작업이 성공한 것이에요.

4단계: 번들 분할

4.1 모든 번들을 나열해요.

입력:

bin/pulsar-admin namespaces bundles public/default

출력:

출력은 번들 수가 17임을 보여줘요.

{
  "boundaries" : [ "0x00000000", "0x08000000", "0x10000000", "0x20000000", "0x30000000", "0x40000000", "0x50000000", "0x60000000", "0x70000000", "0x80000000", "0x90000000", "0xa0000000", "0xb0000000", "0xc0000000", "0xd0000000", "0xe0000000", "0xf0000000", "0xffffffff" ],
  "numBundles" : 17
}

4.2 분할할 범위 public/default/0x00000000_0x08000000을 지정해요.

입력:

bin/pulsar-admin namespaces split-bundle --bundle 0x00000000_0x08000000 public/default

출력:

출력이 없으면 작업이 성공한 것이에요.

tip

  • 기본 번들 분할 알고리즘은 range_equally_divide예요. 다음 방법 중 하나로 다른 번들 분할 알고리즘으로 바꿀 수 있어요.

    • broker.conf 파일에서 defaultNamespaceBundleSplitAlgorithm 업데이트
    • pulsar-admin namespaces split-bundle 사용
  • 번들 분할 임계값은 broker.conf 파일에서 더 많은 구성을 설정할 수 있어요. 임계값 중 하나라도 초과하는 기존 번들은 분할 후보가 돼요.

note

수동 설정은 자동 구성을 덮어써요. 예를 들어 range_equally_divide가 기본 번들 분할 알고리즘이지만, 번들 분할 알고리즘을 수동으로 topic_count_equally_divide로 설정하면 topic_count_equally_divide가 사용돼요.

4.3 번들이 분할되었는지 확인해요.

입력:

bin/pulsar-admin namespaces bundles public/default

출력:

출력은 번들 수가 18(17에서 증가)임을 보여주며, 즉 번들이 분할되었음을 의미해요.

{
  "boundaries" : [ "0x00000000", "0x04000000", "0x08000000", "0x10000000", "0x20000000", "0x30000000", "0x40000000", "0x50000000", "0x60000000", "0x70000000", "0x80000000", "0x90000000", "0xa0000000", "0xb0000000", "0xc0000000", "0xd0000000", "0xe0000000", "0xf0000000", "0xffffffff" ],
  "numBundles" : 18
}

5단계: 토픽과 브로커 사이의 소유권 확인

토픽(파티션)과 브로커 사이의 소유권을 확인해요. 이 단계는 6단계(Unload bundles)의 결과를 확인하기 위한 준비예요.

입력:

bin/pulsar-admin topics partitioned-lookup persistent://public/default/topic-manual

출력:

출력은 더 많은 파티션이 broker 1에 속함을 보여줘요.

persistent://public/default/topic-manual-2-partition-0    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-1    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-2    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-3    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-4    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-5    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-6    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-7    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-8    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-9    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-10    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-11    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-12    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-13    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-14    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-15    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-16    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-17    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-18    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-19    pulsar://broker-1:6650

6단계: 번들 언로드

6.1 번들 범위 public/default/0x10000000_0x20000000을 언로드하고 broker 1에 번들을 할당해요.

입력:

bin/pulsar-admin namespaces unload public/default -b 0x10000000_0x20000000 -d http://broker-1:8080

출력:

출력이 없으면 작업이 성공한 것이에요.

6.2 토픽(파티션)과 브로커 사이의 소유권을 확인해 이 범위가 언로드되었는지 확인해요.

입력:

bin/pulsar-admin topics partitioned-lookup persistent://public/default/topic-manual

출력:

5단계(Check ownerships between topics and brokers)의 결과와 비교하면, 출력은 더 많은 파티션이 broker 2에 속함을 보여줘요.

persistent://public/default/topic-manual-2-partition-0    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-1    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-2    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-3    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-4    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-5    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-6    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-7    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-8    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-9    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-10    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-11    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-12    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-13    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-14    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-15    pulsar://broker-2:6650
persistent://public/default/topic-manual-2-partition-16    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-17    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-18    pulsar://broker-1:6650
persistent://public/default/topic-manual-2-partition-19    pulsar://broker-2:6650
  • 포괄적 이해와 핵심 통찰은 Broker load balancing | Overview.
  • 다양한 사용 시나리오는 Broker load balancing | Use cases.
  • 기능 탐구는 Broker load balancing | Features.
  • 장점 이해는 Broker load balancing | Benefits.
  • 핵심 기초 학습은 Broker load balancing | Concepts.
  • 다양한 로드 밸런서 버전 검토는 Broker load balancing | Types.
  • 한 브로커 로드 밸런서 유형에서 다른 유형으로의 마이그레이션은 Broker load balancing | Migration.
  • extensible 로드 밸런서의 설계 아이디어와 구현 세부 사항은 PIP-192: New Pulsar Broker Load Balancer.

더 알아보기 (Learn more)

  • 로드 밸런싱 전반과 핵심 개념은 Overview·Concepts 문서를 참고해요.
  • 로드 밸런서 유형과 마이그레이션은 Types·Migration 문서를 참고해요.
  • 번들·할당·언로드 전략은 Concepts 문서를 참고해요.
  • 번들 수 구성은 Namespace bundles 문서를 참고해요.