Pulsar load balance

Pulsar broker集群负载均衡

Pulsar 是一个横向可伸缩的消息系统,其中一个核心需求是:一个逻辑集群中的流量必须尽可能均匀地分布在所有可用的 Pulsar broker 上。

您可以使用多种设置和工具来控制流量分布,这需要了解一些如何在 Pulsar 中管理流量的背景知识。 当然,在大多数情况下,上面提到的核心需求是开箱即用的,您不必担心。

Pulsar 负载管理架构

接下来的部分介绍了 Pulsar 负载管理器(load manager)的基本结构。

动态给 broker 分配 topic

Pulsar 会根据集群所有 broker 的负载情况,动态地将 topic 分配给 broker。

新出现的 topic 都会触发负载检测,会选择出最适合的 broker 来认领这个 topic 的所有权(ownership)。

In case of partitioned topics, different partitions are assigned to different brokers. Here “topic” means either a non-partitioned topic or one partition of a topic.

分配的速度会很快,看起来就像是在 “无缝切换”。 例如有 broker 崩溃,它的 topic 将被立即重新分配给另一个 broker 。 还有种情况是 broker 已经过载。 在过载情况下,topic 就会被重新分配给负载较少的 broker。

Broker 的无状态特性让动态分配成为可能,因此你可以根据使用情况快速扩容或缩小集群规模。

分配粒度

向 broker 分配 topic 或分区不是在 topic 或分区级别完成的,而是在 Bundle 级别(更高级别)完成的。 目的是为了摊销需要跟踪的信息数量。 主题基于 CPU、内存、流量负载和其他索引项动态地分配给特定 broker。

与单个 topic 或分区分配不同,每个 broker 拥有一个命名空间下所有 topic 的一个子集的所有权(ownership)。 This subset is called a “bundle“ and effectively this subset is a sharding mechanism.

命名空间是 “管理” 单位: 许多配置调整和操作都是在命名空间级别完成的。

具体分配策略是,命名空间切分为一个 ”bundles“ 列表,每个 bundle 覆盖命名空间的一段哈希值范围。

每个主题会根据其主题名称算出的哈希值。并根据该哈希值来判断,主题需要分到哪一个特定的bundle。

每个 bundle 都是独立的,因此会被独立的分配到不同的 broker。

创建命名空间和包

当你创建一个新的命名空间时,这个命名空间将使用默认的 bundle 数量。 您可以在 conf/broker.conf 中设置此选项:

  1. # 当命名空间创建时没有指定 bundle 数量时,将使用这个默认的值。
  2. defaultNumberOfNamespaceBundles=4

你可以更改系统默认设置,或者在创建新的命名空间时指定这个值:

  1. $ bin/pulsar-admin namespaces create my-tenant/my-namespace --clusters us-west --bundles 16

如上命令,创建命名空间时指定了 bundle 数量为16. 因此,这个命名空间里面的所有主题就可以分布到16个 broker 里面。

一般情况下,如果你能预判流量和主题数量,你最好在开始的时候就设置合理的 bundle 数量,而不是等待系统去自动调整分布。

正常情况下, 应设置 bundle 数量大于 broker数量。因为主题是根据哈希自动分布到 bundle 里面的。 例如,命令空间内有1000个主题,可以使用比如 64 个 bundle ,让流量均匀的分布在 16 个broker上。

卸载主题和 bundle

在 Pulsar 中,你能够通过管理操作去 “卸载“ 主题。 Unloading means to close the topics, release ownership and reassign the topics to a new broker, based on current load.

执行卸载操作的时候,客户端会出现一个短暂的延时增加,通常是几十毫秒左右,此时主题将被重新分配。

卸载是负载管理器用来执行负载调度的一种机制,你也可以手动触发卸载操作。例如,你可以在任何 broker 出现超负载之前就纠正之前的分配并重新分配流量。

卸载主题对分配没有影响,因为它仅仅只关闭并重新打开特定主题:

  1. pulsar-admin topics unload persistent://tenant/namespace/topic

如下命令是,卸载命名空间的所有主题,并触发重新分配:

  1. pulsar-admin namespaces unload tenant/namespace

拆分命名空间 bundle

由于 bundle 中主题的负载会随着时间的变化而变化,或者在前期很难预测流量的变化。所以,broker 支持将一个 bundle 拆分为两个。 此时新建的 bundle 会被重新分配到其他的 broker。

拆分操作是基于一些可配置的阈值来判断执行的。 任何已存在的 bundle 如果超过下列任何阈值,则该 bundle 将会被拆分。 默认情况下,新拆出来的 bundle 总是立刻分配到其他的broker,以平衡流量分布。

  1. # 启用/禁用 自动拆分命名空间中的bundle
  2. loadBalancerAutoBundleSplitEnabled=true
  3. # 启用/禁用 自动卸载切分的bundle
  4. loadBalancerAutoUnloadSplitBundlesEnabled=true
  5. # bundle 中最大的主题数, 一旦超过这个值,将触发拆分操作。
  6. loadBalancerNamespaceBundleMaxTopics=1000
  7. # bundle 最大的session数量(生产 + 消费), 一旦超过这个值,将触发拆分操作。
  8. loadBalancerNamespaceBundleMaxSessions=1000
  9. # bundle 最大的msgRate(进+出)的值, 一旦超过这个值,将触发拆分操作。
  10. loadBalancerNamespaceBundleMaxMsgRate=30000
  11. # bundle 最大的带宽(进+出)的值, 一旦超过这个值,将触发拆分操作
  12. loadBalancerNamespaceBundleMaxBandwidthMbytes=100
  13. # 命名空间中最大的 bundle 数量 (用于自动拆分bundle时)
  14. loadBalancerNamespaceMaximumBundles=128

自动负载切分

Pulsar 的负载管理器支持自动的负载切分。 这意味着,当系统检测到某个 broker 过载时,系统会强制将一些流量自动分配到一些低负载的broker。

即当检测到 broker 过载时,broker 将强制 ”卸载“ bundle 的一些流量较大的子集,以降低 broker 的负载。

例如,默认阈值是85%,如果 broker CPU 率使用超过了95%。那么broker 卸载的百分比差会加上5%: 即(95% - 85%) + 5% = 15%

卸载的 bundle 是基于流量(作为cpu,网络,内存的代理指标)来选择的,在上面的例子中,broker 卸载的 bundle 至少要占有整个broker 15%的流量。

默认情况下,自动负载切分是启用的。 你能够通过如下配置项禁用自动负载切分:

  1. # 启用/禁用自动负载拆分
  2. loadBalancerSheddingEnabled=true

关于负载切分的其他配置:

  1. # 负载切分时间间隔。 Broker 定期检查,是否有一些流量需要从一些负载比较高的 broker,转移到负载较低的 broker 上。
  2. loadBalancerSheddingIntervalMinutes=1
  3. # 防止同一个主题,在同一个时间窗口,被多次迁移的时间间隔。
  4. loadBalancerSheddingGracePeriodMinutes=30

Broker 过载阈值

Broker 是基于 CPU、网络和内存使用的阈值来判断是否过载的。 当其中任何一个指标超过阈值时,将会触发切分操作(如果允许的话)。

默认情况下,负载阈值设置为85%:

  1. # 使用阈值确定 broker 是否过载
  2. loadBalancerBrokerOverloadedThresholdPercentage=85

Pulsar 会从系统中采集这些指标的使用情况。

有一种特殊的情况需要注意。以网络指标为例,在某些情况下,Linux 上报的网络接口速率是不正确的,那就必须手动指定该值。 AWS EC2 实例就是这种情况,它的网卡是 1Gbps的,但是系统上报的是 10Gbps。

因为最大的速度是不正确的, Pulsar 负载管理器会认为 broker 还没到达到网卡的最大服务能力,实际上 broker 已经使用完了网卡的所有资源,此时网络传输就会变慢。

你能够使用如下配置项设置网卡的最大速度:

  1. # 覆盖自动获取的网卡最大速度
  2. # 此选项在某些环境中是有用的(例如:EC2 VMs) ,因为Linux报告的网卡最大速度不是 broker 真实的值。
  3. # 因为负载管理器是根据网络使用情况来判断 broker 是否负载,为了确保信息是正确的,你可以通过这个参数来指定正确的值。 这个配置值可以是一个 double 类型的值(比如: 0.8)。
  4. # 能够通过这个配置项在网卡带宽使用完之前,触发负载切分操作。
  5. loadBalancerOverrideBrokerNicSpeedGbps=

当值为空时,Pulsar 将使用系统报告的值。