Pulsar负载均衡原理及优化方案详解

目录
  • 前言
  • Pulsar 负载均衡原理
    • ThresholdShedder 原理
    • 问题原因
  • 优化方案
  • 总结

前言

前段时间我们在升级 Pulsar 版本的时候发现升级后最后一个节点始终没有流量。

虽然对业务使用没有任何影响,但负载不均会导致资源的浪费。

和同事沟通后得知之前的升级也会出现这样的情况,最终还是人工调用 Pulsar 的 admin API 完成的负载均衡。

这个问题我尝试在 Google 和 Pulsar 社区都没有找到类似的,不知道是大家都没碰到还是很少升级集群。

我之前所在的公司就是一个版本走到黑

Pulsar 负载均衡原理

当一个集群可以水平扩展后负载均衡就显得非常重要,根本目的是为了让每个提供服务的节点都能均匀的处理请求,不然扩容就没有意义了。

在分析这个问题的原因之前我们先看看 Pulsar 负载均衡的实现方案。

# Enable load balancer
loadBalancerEnabled=true

我们可以通过这个 broker 的这个配置来控制负载均衡器的开关,默认是打开。

但具体使用哪个实现类来作为负载均衡器也可以在配置文件中指定:

# Name of load manager to use
loadManagerClassName=org.apache.pulsar.broker.loadbalance.impl.ModularLoadManagerImpl

默认使用的是 ModularLoadManagerImpl

    static LoadManager create(final PulsarService pulsar) {
        try {
            final ServiceConfiguration conf = pulsar.getConfiguration();
            // Assume there is a constructor with one argument of PulsarService.
            final Object loadManagerInstance = Reflections.createInstance(conf.getLoadManagerClassName(),
                    Thread.currentThread().getContextClassLoader());
            if (loadManagerInstance instanceof LoadManager) {
                final LoadManager casted = (LoadManager) loadManagerInstance;
                casted.initialize(pulsar);
                return casted;
            } else if (loadManagerInstance instanceof ModularLoadManager) {
                final LoadManager casted = new ModularLoadManagerWrapper((ModularLoadManager) loadManagerInstance);
                casted.initialize(pulsar);
                return casted;
            }
        } catch (Exception e) {
            LOG.warn("Error when trying to create load manager: ", e);
        }
        // If we failed to create a load manager, default to SimpleLoadManagerImpl.
        return new SimpleLoadManagerImpl(pulsar);
    }

broker 启动时会从配置文件中读取配置进行加载,如果加载失败会使用 SimpleLoadManagerImpl 作为兜底策略。

当 broker 是一个集群时,只有 leader 节点的 broker 才会执行负载均衡器的逻辑。

Leader 选举是通过 Zookeeper 实现的。

默然情况下成为 Leader 节点的 broker 会每分钟读取各个 broker 的数据来判断是否有节点负载过高需要做重平衡。

而是否重平衡的判断依据是由 org.apache.pulsar.broker.loadbalance.LoadSheddingStrategy 接口提供的,它其实只有一个函数:

public interface LoadSheddingStrategy {
    /**
     * Recommend that all of the returned bundles be unloaded.
     * @return A map from all selected bundles to the brokers on which they reside.
     */
    Multimap<String, String> findBundlesForUnloading(LoadData loadData, ServiceConfiguration conf);
}

根据所有 broker 的负载信息计算出一个需要被 unload 的 broker 以及 bundle。

这里解释下 unload 和 bundle 的概念:

  • bundle 是一批 topic 的抽象,将 bundlebroker 进行关联后客户端才能知道应当连接哪个 broker;而不是直接将 topic 与 broker 绑定,这样才能实现海量 topic 的管理。
  • unload 则是将已经与 broker 绑定的 bundle 手动解绑,从而触发负载均衡器选择一台合适的 broker 重新进行绑定;通常是整个集群负载不均的时候触发。

ThresholdShedder 原理

LoadSheddingStrategy 接口目前有三个实现,这里以官方默认的 ThresholdShedder 为例:

它的实现算法是根据带宽、内存、流量等各个指标的权重算出每个节点的负载值,之后为整个集群计算出一个平均负载值。

# 阈值
loadBalancerBrokerThresholdShedderPercentage=10

当集群中有某个节点的负载值超过平均负载值达到一定程度(可配置的阈值)时,就会触发 unload,以上图为例就会将最左边节点中红色部分的 bundle 卸载掉,然后再重新计算一个合适的 broker 进行绑定。

阈值存在的目的是为了避免频繁的 unload,从而影响客户端的连接。

问题原因

当某些 topic 的流量突然爆增的时候这种负载策略确实可以处理的很好,但在我们集群升级的情况就不一定了。

假设我这里有三个节点:

  • broker0
  • broker1
  • broker2

集群升级时会从 broker2->0 进行镜像替换重启,假设在升级前每个 broker 的负载值都是 10。

  • 重启 broker2 时,它所绑定的 bundle 被 broker0/1 接管。
  • 升级 broker1 时,它所绑定的 bundle 又被 broker0/2 接管。
  • 最后升级 broker0, 它所绑定的 bundle 会被broker1/2 接管。

只要在这之后没有发生流量激增到触发负载的阈值,那么当前的负载情况就会一直保留下去,也就是 broker0 会一直没有流量。

经过我反复测试,现象也确实如此。

./pulsar-perf monitor-brokers --connect-string pulsar-test-zookeeper:2181

通过这个工具也可以查看各个节点的负载情况

优化方案

这种场景是当前 ThresholdShedder 所没有考虑到的,于是我在我们所使用的版本 2.10.3 的基础上做了简单的优化:

  • 当原有逻辑走完之后也没有获取需要需要卸载的 bundle,同时也存在一个负载极低的 broker 时(emptyBundle),再触发一次 bundle 查询。
  • 按照 broker 所绑定的数量排序,选择一个数量最多的 broker 的 第一个 bundle 进行卸载。

修改后打包发布,再走一遍升级流程后整个集群负载就是均衡的了。

但其实这个方案并不严谨,第二步选择的重点是筛选出负载最高的集群中负载最高的 bundle;这里只是简单的根据数量来判断,并不够准确。

正当我准备持续优化时,鬼使神差的我想看看 master 上有人修复这个问题没,结果一看还真有人修复了;只是还没正式发版。

github.com/apache/puls…

整体思路是类似的,只是筛选负载需要卸载 bundle 时是根据 bundle 自身的流量来的,这样会更加精准。

总结

不过看社区的进度等这个优化最终能用还不知道得多久,于是我们就自己参考这个思路在管理台做了类似的功能,当升级后出现负载不均衡时人工触发一个逻辑:

  • 系统根据各个节点的负载情况计算出一个负载最高的节点和 bundle 在页面上展示。
  • 人工二次确认是否要卸载,确认无误后进行卸载。

本质上只是将上述优化的自动负载流程改为人工处理了,经过测试效果是一样的。

Pulsar 整个项目其实非常庞大,有着几十上百个模块,哪怕每次我只改动一行代码准备发布测试时都得经过漫长的编译+ Docker镜像打包+上传私 服这些流程,通常需要1~2个小时;但总的来说收获还是很大的,最近也在提一些 issue 和 PR,希望后面能更深入的参与进社区。

以上就是Pulsar负载均衡原理及优化方案详解的详细内容,更多关于Pulsar负载均衡的资料请关注我们其它相关文章!

(0)

相关推荐

  • Apache Pulsar集群搭建部署详细过程

    目录 一.集群组成说明 二.安装前置条件 三.ZooKeeper集群搭建 四.BookKeeper集群搭建 五.Broker集群搭建 六.docker安装pulsar-dashboard 一.集群组成说明 1.搭建Pulsar集群至少需要3个组件:ZooKeeper集群.BookKeeper集群和Broker集群(Broker是Pulsar的自身实例).这三个集群组件如下:ZooKeeper集群(3个ZooKeeper节点组成)Bookie集群(也称为BookKeeper集群,3个BookKee

  • SpringBoot整合Pulsar的实现示例

    目录 一.添加pom.xml依赖 二.Pulsar 参数类 三.Pulsar 配置类 四.不同消费数据类型的监听器 五.Pulsar的核心服务类 六.Pulsar整合Spring Cloud 一.添加pom.xml依赖 <parent>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-parent</artifactId>  

  • Java使用pulsar-flink-connector读取pulsar catalog元数据代码剖析

    简介 通过 pulsar-flink-connector 读取到 Apache pulsar 中的namespaces.topics的元数据信息. pulsar-flink-connector 的 github: https://github.com/streamnative/pulsar-flink Maven <dependency> <groupId>io.streamnative.connectors</groupId> <artifactId>pu

  • Apache Pulsar结合Hudi构建Lakehouse方案分析

    目录 1. 动机 2. 分析 3. 当前方案 4. 新的Lakehouse存储方案 4.1 新的存储布局 4.2 支持高效Upserts 4.3 将Hudi表当做Pulsar Topic 4.4 可扩展的元数据管理 5. 引用 1. 动机 Lakehouse最早由Databricks公司提出,其可作为低成本.直接访问云存储并提供传统DBMS管系统性能和ACID事务.版本.审计.索引.缓存.查询优化的数据管理系统,Lakehouse结合数据湖和数据仓库的优点:包括数据湖的低成本存储和开放数据格式访

  • Apache Pulsar 微信大流量实时推荐场景下实践详解

    目录 导语 作者简介 实践 1:大流量场景下的 K8s 部署实践 实践 2:非持久化 Topic 的应用 实践 3:负载均衡与 Broker 缓存优化 实践 4:COS Offloader 开发与应用 未来展望与计划 导语 本文整理自 8 月 Apache Pulsar Meetup 上,刘燊题为<Apache Pulsar 在微信的大流量实时推荐场景实践>的分享.本文介绍了微信团队在大流量场景下将 Pulsar 部署在 K8s 上的实践与优化.非持久化 Topic 的应用.负载均衡与 Bro

  • 学会Pulsar Consumer的使用方式

    目录 1.使用前准备 2.PulsarClient 3.Producer 4.Consumer 4.1 第一次使用: 4.2 第二次使用: 4.3 第三次使用: 4.4 第四次使用: 4.5 第五次使用: 重试机制源码分析 4.6 第六次使用 1.使用前准备 引入依赖: <dependency> <groupId>org.apache.pulsar</groupId> <artifactId>pulsar-client</artifactId>

  • Pulsar负载均衡原理及优化方案详解

    目录 前言 Pulsar 负载均衡原理 ThresholdShedder 原理 问题原因 优化方案 总结 前言 前段时间我们在升级 Pulsar 版本的时候发现升级后最后一个节点始终没有流量. 虽然对业务使用没有任何影响,但负载不均会导致资源的浪费. 和同事沟通后得知之前的升级也会出现这样的情况,最终还是人工调用 Pulsar 的 admin API 完成的负载均衡. 这个问题我尝试在 Google 和 Pulsar 社区都没有找到类似的,不知道是大家都没碰到还是很少升级集群. 我之前所在的公司

  • Python排序算法之插入排序及其优化方案详解

    一.插入排序 插入排序与我们平时打扑克牌非常相似,将新摸到的牌插入到已有的牌中合适的位置,而已有的牌往往是有序的. 1.1 执行流程 (1)在执行过程中,插入排序会将序列分为2部分,头部是已经排好序的,尾部是待排序的. (2)从头开始扫描每一个元素,每当扫描到一个元素,就将它插入到头部合适的位置,使得头部数据依然保持有序 1.2 逆序对 数组 <2,3,8,6,1> 的逆序对为:<2,1> ❤️,1> <8,1> <8,6> <6,1>,共

  • Spring Cloud负载均衡及远程调用实现详解

    负载均衡 使用微服务后,为了能够承担高并发的压力,同一个服务可能会启动多个实例.这时候消费者就需要负载均衡,把请求分散到各个实例.负载均衡主要有两种设计: 服务端负载均衡客户端负载均衡 对于传统的分布式服务来说,大多使用服务端负载均衡.一般会使用Nginx或者ELB等工具作为负载均衡器,如下图: 传统负载均衡 而在Spring Cloud中,使用的是「客户端负载均衡」的方式,使用「Ribbon」组件来实现客户端的负载均衡.只要引入了微服务注册中心依赖,就会自动引入Ribbon依赖.客户端负载均衡

  • Tomcat 配置与优化方案详解

    Service.xml Server.xml配置文件用于对整个容器进行相关的配置. <Server>元素: 是整个配置文件的根元素.表示整个Catalina容器. 属性: className:实现了org.apache.catalina.Server接口的类名,标准实现类是org.apache.catalina.core.StandardServer类. Port:Tomcat服务器监听用于关闭Tomcat服务器的命令(必须) Shutdown:发送到端口上用于关闭Tomcat服务器的命令.

  • springboot整合Nginx实现负载均衡反向代理的方法详解

    目录 一.百度百科 二.Nginx作为web服务器 三.Nginx处理请求逻辑图 四.Nginx的优点 五.Nginx应用场景 1.反向代理 2.负载均衡 3.动静分离 六.Nginx的常用命令 1.启动 2.从容停止 3.快速停止 4.强制停止 5.重启 6.重启Nginx服务 七.Nginx配置文件 八.Nginx 配置实例-反向代理实例 1.实现效果 2.准备工作 3.访问过程的分析 4.具体配置 5.最终测试 九.Nginx 的原理 1.mater 和 worker 2.worker 如

  • nginx 负载均衡轮询方式配置详解

    一.概述 Nginx的upstream目前支持的分配算法:1.round-robin 轮询1:1轮流处理请求(默认)每个请求按时间顺序逐一分配到不同的应用服务器,如果应用服务器down掉,自动剔除,剩下的继续轮询.2.weight 权重(加权轮询)通过配置权重,指定轮询几率,权重和访问比率成正比,用于应用服务器性能不均的情况.3.ip_hash 哈希算法每个请求按访问ip的hash结果分配,这样每个访客固定访问一个应用服务器,可以解决session共享的问题.应用服务器如果故障需要手工down掉

  • Nginx+Tomcat+Https 服务器负载均衡配置实践方案详解

    由于需要,得搭建个nginx+tomcat+https的服务器,搜了搜网上的发现总是有错,现在整理了些有用的,备忘. 环境:Centos6.5.JDK1.8.Tomcat8.Nginx1.10.1 准备材料: 1.JDK1.8安装包jdk-8u102-linux-x64.tar.gz 2.Tomcat8安装包apache-tomcat-8.0.37.tar.gz 3.Nginx1.10安装包nginx-1.10.1.tar.gz 1.JDK安装配置 解压并安装到/usr/local/jdk [r

  • 前端JS图片懒加载原理方案详解

    目录 背景 原理 方案 方案一:img的loading属性设为“lazy” 使用方法 优点 兼容性 缺点 方案二:通过offsetTop来计算是否在可视区域内 优化 优点 缺点 方案三:通过getBoundingClientRect来计算是否在可视区域内 方案四:使用IntersectionObserver来判断是否在可视区域内 兼容性 优点 缺点 问题 布局抖动 响应式图片 SEO不友好 插件 背景 懒加载经常出现在前端面试中,是前端性能优化的常用技巧.懒加载也叫延迟加载,把非关键资源先不加载

  • SpringCloud LoadBalancerClient 负载均衡原理解析

    目录 深入解析 LoadBalancerClient 接口源码: 1.LoadBalancerClient 源码解析: 2.ILoadBalancer 源码解析: LoadBalancerClient 是 SpringCloud 提供的一种负载均衡客户端,Ribbon 负载均衡组件内部也是集成了 LoadBalancerClient 来实现负载均衡.那么 LoadBalancerClient 内部到底是如何做到的呢?我们先大概讲一下 LoadBalancerClient 的实现原理,然后再深入源

  • Redis的持久化方案详解

    Redis支持RDB与AOF两种持久化机制,持久化可以避免因进程异常退出或down机导致的数据丢失问题,在下次重启时能利用之前的持久化文件实现数据恢复. RDB持久化 RDB持久化即通过创建快照(压缩的二进制文件)的方式进行持久化,保存某个时间点的全量数据.RDB持久化是Redis默认的持久化方式.RDB持久化的触发包括手动触发与自动触发两种方式. 手动触发 save, 在命令行执行save命令,将以同步的方式创建rdb文件保存快照,会阻塞服务器的主进程,生产环境中不要用 bgsave, 在命令

随机推荐