Quick start

Broker load balancing helps you distribute messages evenly among brokers and ensure efficient utilization of resources across Pulsar clusters.

This tutorial guides you through the steps for getting started with broker load balancing using Pulsar 3.0.0 in Docker.

Prerequisites

  • Install Pulsar:

    • If you want to run the modular load balancer, use Pulsar 1.7.0 or later versions.

    • If you want to run the extensible load balancer, use Pulsar 3.0.0 or later versions.

  • Install Docker and allocate at least 8 GB of memory.

Configure broker load balancer to run automatically

If you want to use broker load balancing automatically, follow the steps below.

Step 1. Start ZooKeeper, bookie, and broker

Create a docker-compose.yaml file and copy the following code to that file.

This example starts a ZooKeeper server, a bookie, and 2 brokers, sets the load balancer type to extensible, sets the unloading strategy to TransferShedder, and enables debug mode.

  1. version: '3'
  2. networks:
  3. pulsar:
  4. driver: bridge
  5. services:
  6. # Start ZooKeeper
  7. zookeeper:
  8. image: apachepulsar/pulsar:3.0.1
  9. container_name: zookeeper
  10. restart: on-failure
  11. networks:
  12. - pulsar
  13. volumes:
  14. - ./data/zookeeper:/pulsar/data/zookeeper
  15. environment:
  16. - metadataStoreUrl=zk:zookeeper:2181
  17. - PULSAR_MEM=-Xms256m -Xmx256m -XX:MaxDirectMemorySize=256m
  18. command: >
  19. bash -c "bin/apply-config-from-env.py conf/zookeeper.conf && \
  20. bin/generate-zookeeper-config.sh conf/zookeeper.conf && \
  21. exec bin/pulsar zookeeper"
  22. healthcheck:
  23. test: ["CMD", "bin/pulsar-zookeeper-ruok.sh"]
  24. interval: 10s
  25. timeout: 5s
  26. retries: 30
  27. # Initialize cluster metadata
  28. pulsar-init:
  29. container_name: pulsar-init
  30. hostname: pulsar-init
  31. image: apachepulsar/pulsar:3.0.1
  32. networks:
  33. - pulsar
  34. command: >
  35. bin/pulsar initialize-cluster-metadata \
  36. --cluster cluster-a \
  37. --zookeeper zookeeper:2181 \
  38. --configuration-store zookeeper:2181 \
  39. --web-service-url http://broker:8080 \
  40. --broker-service-url pulsar://broker:6650
  41. depends_on:
  42. zookeeper:
  43. condition: service_healthy
  44. # Start bookie
  45. bookie:
  46. image: apachepulsar/pulsar:3.0.1
  47. container_name: bookie
  48. restart: on-failure
  49. networks:
  50. - pulsar
  51. environment:
  52. - clusterName=cluster-a
  53. - zkServers=zookeeper:2181
  54. - metadataServiceUri=metadata-store:zk:zookeeper:2181
  55. - advertisedAddress=bookie
  56. - BOOKIE_MEM=-Xms512m -Xmx512m -XX:MaxDirectMemorySize=256m
  57. depends_on:
  58. zookeeper:
  59. condition: service_healthy
  60. pulsar-init:
  61. condition: service_completed_successfully
  62. volumes:
  63. - ./data/bookkeeper:/pulsar/data/bookkeeper
  64. command: bash -c "bin/apply-config-from-env.py conf/bookkeeper.conf && exec bin/pulsar bookie"
  65. # Start broker 1
  66. broker-1:
  67. image: apachepulsar/pulsar:3.0.1
  68. container_name: broker-1
  69. hostname: broker-1
  70. restart: on-failure
  71. networks:
  72. - pulsar
  73. environment:
  74. - metadataStoreUrl=zk:zookeeper:2181
  75. - zookeeperServers=zookeeper:2181
  76. - clusterName=cluster-a
  77. - managedLedgerDefaultEnsembleSize=1
  78. - managedLedgerDefaultWriteQuorum=1
  79. - managedLedgerDefaultAckQuorum=1
  80. - advertisedAddress=broker-1
  81. - internalListenerName=internal
  82. - advertisedListeners=internal:pulsar://broker-1:6650
  83. - brokerServicePort=6650
  84. - webServicePort=8080
  85. - PULSAR_MEM=-Xms128m -Xmx2096m -XX:MaxDirectMemorySize=256m
  86. # Load Manager. Here uses the extensible load balancer, sets the unloading strategy to TransferShedder, and enables debug mode.
  87. - loadManagerClassName=org.apache.pulsar.broker.loadbalance.extensions.ExtensibleLoadManagerImpl
  88. - loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.extensions.scheduler.TransferShedder
  89. - PULSAR_PREFIX_loadBalancerDebugModeEnabled=true
  90. depends_on:
  91. zookeeper:
  92. condition: service_healthy
  93. bookie:
  94. condition: service_started
  95. command: bash -c "bin/apply-config-from-env.py conf/broker.conf && exec bin/pulsar broker"
  96. # Start broker 2
  97. broker-2:
  98. image: apachepulsar/pulsar:3.0.1
  99. container_name: broker-2
  100. hostname: broker-2
  101. restart: on-failure
  102. networks:
  103. - pulsar
  104. environment:
  105. - metadataStoreUrl=zk:zookeeper:2181
  106. - zookeeperServers=zookeeper:2181
  107. - clusterName=cluster-a
  108. - managedLedgerDefaultEnsembleSize=1
  109. - managedLedgerDefaultWriteQuorum=1
  110. - managedLedgerDefaultAckQuorum=1
  111. - advertisedAddress=broker-2
  112. - internalListenerName=internal
  113. - advertisedListeners=internal:pulsar://broker-2:6650
  114. - webServicePort=8080
  115. - brokerServicePort=6650
  116. - PULSAR_MEM=-Xms128m -Xmx2096m -XX:MaxDirectMemorySize=256m
  117. # Load Manager. Here uses the extensible load balancer, sets the unloading strategy to TransferShedder, and enables debug mode.
  118. - loadManagerClassName=org.apache.pulsar.broker.loadbalance.extensions.ExtensibleLoadManagerImpl
  119. - loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.extensions.scheduler.TransferShedder
  120. - PULSAR_PREFIX_loadBalancerDebugModeEnabled=true
  121. depends_on:
  122. zookeeper:
  123. condition: service_healthy
  124. bookie:
  125. condition: service_started
  126. command: bash -c "bin/apply-config-from-env.py conf/broker.conf && exec bin/pulsar broker"

Quick start - 图1tip

If you use other ways instead of using a yaml file as above, you can choose a broker load balancer type or set an unloading strategy by updating loadManagerClassName or loadBalancerLoadSheddingStrategy in the broker.conf file

It is not recommended to use the pulsar-admin update-dynamic-config) because it will throw an exception if the Pulsar version and the unloading strategy are incompatible.

Step 2. Start a Pulsar cluster

2.1 Open a tab in the terminal (i.e., terminal tab 1) and execute the following commands.

2.2 Start a Pulsar cluster.

Input

  1. docker compose up -d

Output

The output shows that the broker 1 and broker 2 are running.

  1. [+] Running 12/12
  2. broker-1 Pulled 242.5s
  3. zookeeper Pulled 242.5s
  4. broker-2 Pulled 242.5s
  5. pulsar-init Pulled 242.5s
  6. bookie 7 layers [⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 242.5s
  7. 3153aa388d02 Already exists 0.0s
  8. 5d127458ab3b Pull complete 83.3s
  9. 1f99067df50d Pull complete 160.0s
  10. 85fd7b6fa5dc Pull complete 160.0s
  11. ff6d7ec52b64 Pull complete 160.0s
  12. b53efccabef0 Pull complete 238.5s
  13. 6425449412d7 Pull complete 238.8s
  14. [+] Running 11/11
  15. Network docker_pulsar Created 0.1s
  16. Container zookeeper Healthy 25.1s
  17. ! 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
  18. ✔ Container pulsar-init Exited 24.0s
  19. ! 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
  20. Container bookie Started 24.2s
  21. ! 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
  22. ✔ Container broker-1 Started 25.0s
  23. ✔ Container broker-2 Started 25.0s
  24. ! 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
  25. ! 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

Step 3. Check the status of broker and load balancer (Optional)

In terminal tab 1, execute the following commands.

3.1 Enter the container of broker 1.

Input

  1. docker exec -it broker-1 bash

Output

If there is no output, the operation is successful.

3.2 Display the list of brokers in your cluster.

Input

  1. bin/pulsar-admin brokers list my-cluster

Output

The output shows there are 2 brokers.

  1. broker-2:8081
  2. broker-1:8080

3.3 Verify the load balancer type.

Input

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

Output

The output shows the load balancer type is extensible.

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

Step 4. Create a topic

In terminal tab 1, execute the following commands.

4.1 Enter the container of broker 1.

Input

  1. docker exec -it broker-1 bash

Output

If there is no output, the operation is successful.

4.2 Create a partitioned topic named my-topic-1 with 2000 partitions under my-tenant-1/my-namespace-1.

Quick start - 图2tip

This example simplifies the task by only specifying 1 bundle. For details on how to set a reasonable number of bundles, see defaultNumberOfNamespaceBundles.

Input

  1. bin/pulsar-admin tenants create my-tenant-1
  2. 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

Output

If there is no output, the operation is successful.

4.3 Produce messages to the topic using the pulsar-perf tool.

Input

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

Output

The output shows that messages have been produced.

  1. 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: {
  2. ...

Step 5. Split bundles

5.1 Open another tab in the terminal (i.e., terminal tab 2) and execute the following commands.

5.2 Enter the container of broker 2.

Input

  1. docker exec -it broker-2 bash

Output

If there is no output, the operation is successful.

5.3 Verify whether the bundles are split after 5 minutes. It takes a little time for Pulsar to split bundles.

Quick start - 图3tip

Input

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

Output

The output shows that the bundle has been split into 3 ranges.

  1. {
  2. "boundaries" : [ "0x00000000", "0x3fffffff", "0x7fffffff", "0xffffffff" ],
  3. "numBundles" : 3
  4. }

Quick start - 图4note

The number of bundles may vary depending on the time. For example, if you wait longer than 5 minutes, the number of bundles may increase. If the number of bundles is equal to or greater than 2, it means that the bundle has been split.

Step 6. Unload bundles

You can verify if a bundle has been unloaded using the metric pulsar_lb_unload_bundle_total. This method is only supported in the automatic way.

Quick start - 图5tip

  • The automatic bundle unloading is enabled by default. To disable it, update loadBalancerSheddingEnabled to false in the broker.conf file.

  • The default bundle unloading strategy is TransferShedder (for the extensible broker load balancer) or ThresholdShedder (for the modular broker load balancer). You can change it to other bundle unloading strategies by updating loadBalancerLoadSheddingStrategy in the broker.conf file.

  • For bundle unloading conditions, you can set more configurations in the broker.conf file.

Configure broker load balancer to run manually

If you want to use broker load balancing manually, follow the steps below.

Step 1. Start ZooKeeper, bookie, and broker

This is the same as Step 1. Start ZooKeeper, bookie, and broker in the automatic method.

Step 2. Start a Pulsar cluster

This is the same as Step 2. Start a Pulsar cluster in the automatic method.

Step 3. Create a topic

3.1 Enter the container of broker 1.

Input

  1. docker exec -it broker-1 bash

Output

If there is no output, the operation is successful.

3.2 Create a partitioned topic named topic-manual with 20 partitions under public/default.

Input

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

Output

If there is no output, the operation is successful.

Step 4. Split bundles

4.1 List all bundles.

Input

  1. bin/pulsar-admin namespaces bundles public/default

Output

The output shows that the number of bundles is 17.

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

4.2 Specify the range public/default/0x00000000_0x8000000 to be split.

Input

  1. bin/pulsar-admin namespaces split-bundle --bundle 0x00000000_0x10000000 public/default

Output

If there is no output, the operation is successful.

Quick start - 图6tip

Quick start - 图7note

Manual settings will override automatic configurations. For example, range_equally_divide is the default bundling splitting algorithm, but if you manually set the bundling splitting algorithm to topic_count_equally_divide, then topic_count_equally_divide is used.

4.3 Verify if the bundle has been split.

Input

  1. bin/pulsar-admin namespaces bundles public/default

Output

The output shows that the number of bundles is 18 (increased from 17), which means the bundle has been split.

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

Step 5. Check ownerships between topics and brokers

Check the ownerships between topics (partitions) and brokers. This step is preparing to verify the result for Step 6. Unload bundles.

Input

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

Output

The output shows that more partitions belong to the broker 1.

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

Step 6. Unload bundles

6.1 Unload the bundle range public/default/0x10000000_0x20000000 and allocate bundles to broker 1.

Input

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

Output

If there is no output, the operation is successful.

6.2 Verify if this range has been unloaded by checking the ownerships between topics (partitions) and brokers.

Input

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

Output

Compared to the result of Step 5. Check ownerships between topics and brokers, the output shows that more partitions belong to the broker 2.

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