关于作者

鲍明宇

腾讯高档软件工程师,现在上任于腾讯 TEG 数据渠道部,担任 Apache Pulsar、Apache Inlong、DB 数据采集等项意图开发作业。现在专注于大数据范畴,音讯中间件、大数据数据接入等方向,拥有 10 年 Java 相关开发经验。

张大伟

腾讯高档软件工程师,Apache Pulsar Committer,现在上任于腾讯 TEG 数据渠道部,首要担任 Apache Pulsar 项目相关作业。现在专注于 MQ 和数据实时处理等范畴,拥有 6 年大数据渠道相关开发经验。

关于 Apache Pulsar

云原生年代音讯行列和流交融体系,供给一致的消费模型,支撑音讯行列和流两种场景,既能为行列场景供给企业级读写服务质量和强一致性确保,又能为流场景供给高吞吐、低推迟;选用存储核算分离架构,支撑大集群、多租户、百万级 Topic、跨地域数据仿制、持久化存储、分层存储、高可扩展性等企业级和金融级功能。

GitHub 地址:github.com/apache/puls…

导读

近期,腾讯 TEG 数据平部 MQ 团队开发布置了一套底层运维目标功能剖析体系(本文简称 Data 项目) ,现在作为通用基础设施服务整个腾讯集团。该体系旨在搜集功能目标、上报数据以用于事务的运维监控,后续也将延用至前后端实时剖析场景。

腾讯 Data 项目选用 Apache Pulsar 作为音讯体系,其服务端选用 CVM 服务器(Cloud Virtual Machine,CVM)布置,并将出产者和顾客布置在 Kubernetes 上,该项目 Pulsar 集群是腾讯数据渠道部 MQ 团队接入的音讯量最大的 Pulsar 集群。在整个项目中,咱们在 Apache Pulsar 大规模集群运维进程中遇到了一些问题和应战。本文将对这些问题展开描绘剖析,并同享对应处理计划,一同也会解析涉及到的相关 Apache Pulsar 规划原理。

希望本文能够对面临同类场景的用户与开发者供给参阅。

事务音讯量大,对出产与消费耗时目标灵敏

Data 项意图事务场景,具有十分显着的特色。首要,事务体系运转进程中,音讯的出产、消费量都十分大,而且出产音讯的 QPS(每秒查询率)波动性不显着,即事务会在近乎固定的 QPS 出产和消费数据。

其次,事务方对体系的可靠性、出产耗时、消费耗时这几个目标项比较灵敏,需求在比较低的推迟基础上完成事务处理流程。像 Data 项目这样的事务场景和需求,对集群的布置、运营和体系安稳性都提出了十分高的要求。

Data 项目集群最大的特色是音讯量大、节点多,一个订阅里可高达数千顾客。虽然 Data 项目当时 Topic 总量并不多,但单个 Topic 对应的客户端比较多,每个分区要对应 100+ 个出产者和 10000+个顾客。在对音讯体系选型时,团队将音讯体系的低推迟、高吞吐设为要害目标。通过归纳比照市面上常见的音讯体系,Apache Pulsar 凭借其功能和功能胜出。

Apache Pulsar 供给了诸多消费模型如独占、故障搬运、同享(Shared)和键同享(Key_Shared),其中在 Key_Shared 和 Shared 订阅下能够支撑许多顾客节点。其他音讯流体系如 Kafka,因为顾客节点受限于分区个数,导致其在多分区时功能相对较低。(编者注: Pulsar 和 Kafka 的最新功能测评,敬请期待 StreamNative 行将发布的 2022 版陈述)

超大 Pulsar 集群:单分区最大顾客数量超8K

现在 Data 项目事务数据接入两套 Pulsar 集群,分为 T-1 和 T-2。其中,T-1 对接的事务的客户端 Pod(分为出产者和顾客,且不在同一个 Pod 上,布置在腾讯云容器化渠道 (STKE) ,与 Pulsar 集群在相同机房;T-2 对接事务的客户端 Pod 与 Pulsar 集群不在相同的机房(注:机房之间的数据时延比较同机房内部略高)。

服务器侧相关参数

序号 参数 概况 补白
1 集群 数 2 T-1/ T-2
2 机器数量 100+台/集群 CVM IT5(非物理机/64 核/256G 内存/ 4 SSD)
3 Broker 数量 100+ 2.8.1.2(内部版别),布置三台 Discovery 服务
4 Bookie 数量 100+
5 Discovery 服务 3/集群 与 Bookie 混合布置在同一台机器上面
6 ZooKeeper 数量 5/每集群 3.6.3 版别,单独布置,运用 SA2.4XLARGE32 机型
7 布置方法 Broker+Bookie 混合布置在同一台机器上面
8 Topic 数 3/集群
9 分区数 100+/Topic
10 音讯副本数 2 副本写入战略:E=5, W=2, A=2
11 音讯保存时长 1 天 Retention\TTL 均装备为 1 天
12 namespace 数 3 每个 namespace下一个 Topic
13 当时音讯量/天(按照每条音讯巨细 4k 均值评估) 千亿 /天/集群
14 当时音讯量/分钟 千万/分钟

事务侧相关参数

Data 项目事务侧运用 Go 言语开发,接入 Pulsar 集群运用 Pulsar Go Client 社区 Master 分支的最新版别。运用云梯 STKE 容器方法布置。

序号 参数 描绘 补白
1 单分区最大出产者数量 150左右
2 单分区最大顾客数量 1w个左右 单分区这个量,服务器端需求保护许多的元数据信息
3 客户端接入方法 Go SDK 现在运用 Master 分支最新代码
4 出产者 Pod 数量 150左右
5 顾客 Pod 数量 1w个左右
6 客户端布置渠道 STKE 腾讯内部的腾讯云容器服务渠道

本文接下来将介绍 Pulsar 客户端在多种场景下的功能调优,别离针对项目在运用 Pulsar 的进程中遇到的客户端出产超时、客户端频频断开等情况进行原因解析,并供给咱们的解决计划,供咱们参阅。

客戶端功能调优:问题与计划

调优一:客户端出产超时,服务器端排查

在大集群下,导致客户端出产音讯耗时较长或出产超时的原因有许多,咱们先来看几个服务器端的原因,包含:

  • 音讯承认信息过大(承认空泛)
  • Pulsar-io 线程卡死
  • Ledger 切换耗时过长
  • BookKeeper-io 单线程耗时过长
  • DEBUG 等级日志影响
  • Topic 分区数据散布不均\

接下来,针对每个或许的服务器端原因,咱们逐个进行解析。

解析 1:消费承认信息过大(承认空泛)

与 Kafka、RocketMQ、TubeMQ 等不同,Apache Pulsar 不仅仅会针对每个订阅的消费进展保存一个最小的承认方位(即这个方位之前的音讯都现已被承认已消费),也会针对这个方位之后且现已收到承认呼应的音讯,用 range 区间段的方法保存承认信息。

如下图所示:

千亿级、大规模:腾讯超大 Apache Pulsar 集群性能调优实践

别的,因为 Pulsar 的每个分区都会对应一个订阅组下的所有顾客。Broker 向客户端推送音讯的时分,通过轮询的方法(此处指 Shared 同享订阅;Key_Shared 订阅是通过 key 与一个顾客做相关来进行推送)给每个顾客推送一部分音讯。每个顾客别离承认一部分音讯后,Broker 端或许会保存许多这种承认区段信息。

如下图所示:

千亿级、大规模:腾讯超大 Apache Pulsar 集群性能调优实践

承认空泛是两个连续区间之间的点,用于表明承认信息的区间段的个数。承认空泛受相同订阅组下顾客个数的多少、顾客消费进展的快慢等因素的影响。空泛较多或特别多即表明消费承认的信息十分大。

Pulsar 会周期性地将每个消费组的承认信息组成一个 Entry,写入到 Bookie 中进行存储,写入流程与一般音讯写入流程一样。因而当消费组的消费承认空泛比较多、消费承认信息比较大、写入比较频频的时分,会对体系的全体呼应机制发生压力,在客户端表现为出产耗时增加、出产超时增多、耗时毛刺显着等现象。

在此情况下,能够通过减少顾客个数、进步顾客消费速率、调整保存承认信息的频率和保存的 range 段的个数等方法处理承认空泛。

解析 2:Pulsar-io 线程卡死

Pulsar-io 线程池是 Pulsar Broker 端用于处理客户端恳求的线程池。当这儿的线程处理慢或卡住的时分,会导致客户端出产超时、衔接断连等。Pulsar-io 线程池的问题,能够通过 jstack 信息进行剖析,在 Broker 端表现为存在许多的 CLOSE_WAIT 情况的衔接, 如下图所示:

千亿级、大规模:腾讯超大 Apache Pulsar 集群性能调优实践

Pulsar-io 线程池卡住的现象,一般为服务器端代码 bug 导致,现在处理过的有:

  • 部分并发场景发生的死锁;
  • 异步编程 Future 反常分支未处理完毕等。

除了程序本身的 bug 外,装备也或许引起线程池卡住。假如 Pulsar-io 线程池的线程长时刻处于运转情况,在机器 CPU 资源满足的情况下,能够通过变更 broker.conf 中的 numioThreads 参数来调整 Pulsar-io 线程池中的作业线程个数,来进步程序的并行处理功能。

注意:Pulsar-io 线程池繁忙,本身并不会导致问题。 可是,Broker 端有一个后台线程,会周期的判别每一个 Channel(衔接)有没有在阈值时刻内收到客户端的恳求信息。假如没有收到,Broker 会主动的封闭这个衔接(相反,客户端 SDK 中也有相似的逻辑)。因而,当 Pulsar-io 线程池被卡住或许处理慢的时分,客户端会呈现频频的断连-重联的现象。

解析 3:Ledger 切换耗时过长

Ledger 作为 Pulsar 单个分区音讯的一个逻辑组织单位,每个 Ledger 下包含必定巨细和数量的 Entry,而每个 Entry 下会保存至少一条音讯( batch 参数敞开后,或许是多条)。每个 Ledger 在满足必定的条件时,如包含的 Entry 数量、总的音讯巨细、存活的时刻三个维度中的任何一个超过装备限制,都会触发 Ledger 的切换。

Ledger 切换时刻耗时比较长的现象如下:

千亿级、大规模:腾讯超大 Apache Pulsar 集群性能调优实践

当 Ledger 发生切换时,Broker 端新接收到或还未处理完的音讯会放在 appendingQueue 行列中,当新的 Ledger 创立完成后,会继续处理这个行列中的数据,确保音讯不丢掉。

因而,当 Ledger 切换进程比较慢时会导致音讯出产的耗时比较长甚至超时。这个场景下,一般需求重视下 ZooKeeper 的功能,排查下 ZooKeeper 所在机器的功能和 ZooKeeper 进程的 GC 情况。

解析 4:BookKeeper-io 单线程耗时过长

现在 Pulsar 集群中,BookKeeper 的版别要比较照较安稳,一般通过调整相应的客户端线程个数、保存数据时的 E、QW、QA 等参数能够达到预期的功能。

假如通过 Broker 的 jstack 信息发现 BookKeeper 客户端的 Bookkeeper-io 线程池比较繁忙时或线程池中的单个线程比较繁忙时,首要要排查 ZooKeeper、Bookie 进程的 Full GC 情况。假如没有问题,能够考虑调整 Bookkeeper-io 线程池的线程个数和 Topic 的分区数。

解析 5:Debug 等级日志影响

在日志等级下,影响出产耗时的场景一般呈现在 Java 客户端。如客户端事务引入的是 Log4j,运用的是 Log4j 的日志输出方法,一同敞开了 Debug 等级的日志则会对 Pulsar Client SDK 的功能有必定的影响。主张运用 Pulsar Java 程序引入 Log4j 或 Log4j + SLF4J 的方法输出日志。一同,针对 Pulsar 包调整日志等级至少到 INFO 或 ERROR 等级。

在比较夸张的情况下,Debug 日志影响出产耗时的线程能将出产耗时拉长到秒等级,调整后降低到正常水平(毫秒级)。具表现象如下:

千亿级、大规模:腾讯超大 Apache Pulsar 集群性能调优实践

在音讯量特别大的场景下,服务器端的 Pulsar 集群需求封闭 Broker、Bookie 端的 Debug 等级的日志打印(主张线网环境),直接将日志调整至 INFO 或 ERROR 等级。

解析 6:Topic 分区散布不均

Pulsar 会在每个 Namespace 等级装备 bundles ,默许 4 个,如下图所示。每个 bundle range 规模会与一个 Broker 相关,而每个 Topic 的每个分区会通过 hash 运算,落到对应的 Broker 进行出产和消费。当过多的 Topic 分区落入到相同的 Broker 上面,会导致这个 Broker 上面的负载过高,影响音讯的出产和消费功率。

千亿级、大规模:腾讯超大 Apache Pulsar 集群性能调优实践

中度可信度描绘已自动生成]()Data 项目在开始布置的时分,每个 Topic 的分区数和每个 Namespace 的 bundle 数都比较少。通过调整 Topic 的分区个数和 bundle 的切割个数,使得 Topic 的分区在 Broker 上面达到逐步均衡散布的意图。

在 bundle 的动态切割和 Topic 的散布调整上,Pulsar 仍是有很大的提高空间,需求在 bundle 的切割算法(现在支撑 range_equally_dividetopic_count_equally_divide,默许现在支撑 range_equally_divide,主张运用 topic_count_equally_divide)、Topic 分区的散布层面,在确保体系安稳、负载均衡的情况下做进一步的提高。

调优二:客户端频频断开与重连

客户端断连/重连的原因有许多,结合腾讯 Data 项目场景,咱们总结出客户端 SDK 导致断连的首要有如下几个原因,首要包含:

  • 客户端超时断连-重连机制
  • Go SDK 的反常处理
  • Go SDK 出产者 sequence id 处理
  • 顾客许多、频频的创立和毁掉

下面依次为咱们解析这些问题的原因与解决计划。

解析 1:客户端超时断连-重连机制

Pulsar 客户端 SDK 中有与 Broker 端相似逻辑(可参阅#解析2部分内容),周期判别是否在阈值的时刻内收到服务器端的数据,假如没有收到则会断开衔接。

这种现象,扫除服务器端问题的前提下,一般问题呈现在客户端的机器资源比较少,且运用率比较高的情况,导致应用程序没有满足的 CPU 才能处理服务器端的数据。此种情况,能够调整客户端的事务逻辑或布置方法,进行躲避处理。

解析 2:Go SDK 的反常处理

Pulsar 社区供给多言语的客户端的接入才能,如支撑 Java、Go、C++、Python 等。可是除了 Java 和 Go 言语客户端外,其他的言语完成相对要弱一些。Go 言语的 SDK 相对于 Java 言语 SDK 还有许多当地需求完善和细化,比方说在细节处理上与 Java 言语 SDK 比较还不行细腻。

如收到服务器端的反常时,Java SDK 能够区分哪些反常需求毁掉衔接重连、哪些反常不必毁掉衔接(如 ServerError_TooManyRequests),但 Go 客户端会直接毁掉 Channel ,重新创立。

解析 3:Go SDK 出产者 Sequence id 处理

发送音讯后,低版别的 Go SDK 出产者会收到 Broker 的呼应。假如呼应音讯中的 sequenceID 与本端保护的行列头部的 sequenceID 不相等时会直接断开衔接——这在部分场景下,会导致误断,需求区分小于和大于等于两种场景。

这儿描绘的场景和解析 1-客户端超时中的部分反常场景,现已在高版别 Go SDK 中做了细化和处理,主张咱们在选用 Go SDK 时尽量选用新的版别运用。现在,Pulsar Go SDK 也在快速的迭代中,欢迎感兴趣的同学一同参加和贡献。

解析 4:顾客许多且频频地创立和毁掉

集群运维进程中在更新 Topic 的分区数后,顾客会许多且频频地创立和毁掉。针对这个场景,咱们已排查到是 SDK bug 导致,该问题会在 Java 2.6.2 版别呈现。运维期间,顾客与 Broker 端现已建立了安稳的衔接;运维进程中,因事务音讯量的增加需求,需求调整 Topic 的分区数。客户端在不需求重启的前提下,感知到了服务器端的调整,开始创立新增分区的顾客,这是因为处理逻辑的 bug,会导致客户端许多且频频地重复创立顾客。假如你也遇到相似问题,主张晋级 Java 客户端的版别。 除了上面的断连-重连场景外,在咱们腾讯 Data 项意图客户端还遇到过 Pod 频频重启的问题。通过排查和剖析,咱们确定是客户端呈现反常时,抛出 Panic 过错导致。主张在事务完成时,要考虑相关的容错场景,在完成逻辑层面进行必定程度的躲避。

调优三:晋级 ZooKeeper

因为咱们腾讯 Data 项目中运用的 Pulsar 集群音讯量比较大,机器的负载也相对较高。涉及到 ZooKeeper,咱们开始运用的是 ZooKeeper 3.4.6 版别。在日常运维进程中,整个集群多次触发 ZooKeeper 的一个 bug,现象如下截图所示:

千亿级、大规模:腾讯超大 Apache Pulsar 集群性能调优实践

当时,ZooKeeper 项目现已修正该 Bug,感兴趣的小伙伴能够点击该衔接检查概况:issues.apache.org/jira/browse…。因而,在 Pulsar 集群布置的时分主张打上相应的补丁或晋级 ZooKeeper 版别。在腾讯 Data 项目中,咱们则是挑选将 ZooKeeper 版别晋级到 3.6.3 进行了对应处理。

小结:Pulsar 集群运维排查攻略

不同的事务有不同的场景和要求,接入和运维 Apache Pulsar 集群时遇到的问题,或许也不太一样,但咱们仍是能从问题排查视点方面做个整理,以便找到相应规则提高功率。

针对 Apache Pulsar 集群运维进程中遇到的问题,如出产耗时长、出产超时(timeout)、音讯推送慢、消费堆积等,假如日志中没有什么显着的或有价值的反常(Exception)、过错(Error) 之类的信息时,能够从如下几个方面进行排查:

  • 集群资源装备及运用现状
  • 客户端消费情况
  • 音讯承认信息
  • 线程情况
  • 日志剖析
    下面针对每个方面做个简要说明。

1. 集群资源装备及运用现状

首要,需求排查进程的资源装备是否能够满足当时体系负载情况。能够通过 Pulsar 集群监控仪表盘渠道检查 Broker、Bookie、ZooKeeper 的 CPU、内存及磁盘 IO 的情况。

其次,检查 Java 进程的 GC 情况(特别是 Full GC 情况),处理 Full GC 频频的进程。假如是资源装备方面的问题,需求集群办理人员或许运维人员调整集群的资源装备。

2. 客户端消费情况

能够排查消费才能缺乏引起的反压(背压)。呈现背压的现象一般是存在顾客进程,可是收不到音讯或缓慢收到音讯。 能够通过 Pulsar 办理命令,检查受影响 Topic 的计算信息(stats),可重点重视 未承认音讯数量数量(unackedMessages)backlog 数量消费订阅类型,以及处理未承认音讯(unackmessage)比较大的订阅/顾客。假如未承认音讯(unackmessage)数量过多,会影响 Broker 向客户端的音讯分发推送。这类问题一般是事务侧的代码处理有问题,需求事务侧排查是否有反常分支,没有进行音讯的 ack 处理。

3. 音讯承认信息

假如集群出产耗时比较长或出产耗时毛刺比较多,除了体系资源装备方面排查外,还需求检查是否有过大的音讯承认信息。

检查是否有过大的承认空泛信息,能够通过办理命令针对单个 Topic 运用 stats-internal 信息,检查订阅组中的 individuallyDeletedMessages 字段保存的信息巨细。

音讯承认信息的保存进程与音讯的保存进程是一样的,过大的承认信息假如频频下发存储,则会对集群存储造成压力,从而影响音讯的出产耗时。

4. 线程情况

假如通过上面的过程,问题还没有剖析清楚,则需求再排查下 Broker 端的线程情况,首要重视 pulsar-iobookkeeper-iobookkeeper-ml-workers-OrderedExecutor 线程池的情况,检查是否有线程池资源不行或许线程池中某个线程被长时间占用。

能够运用 top -p PID(详细pid) H 命令,检查当时 CPU 占用比较大的线程,结合 jstack 信息找到详细的线程。

5. 日志剖析

假如通过上面所述过程仍然没有承认问题来源,就需求进一步检查日志,找到含有有价值的信息,并结合客户端、Broker 和 Bookie 的日志及事务的运用特色、问题呈现时的场景、最近的操作等进行归纳剖析。

回忆与计划

上面咱们花了很大篇幅来介绍客户端功能调优的内容,给到客户端出产超时、频频断开与重连、ZooKeeper 等相应的排查思路与解决计划,并汇总了常见 Pulsar 集群问题排查攻略 5 条主张,为在大音讯量、多节点、一个订阅里高达数千顾客的 Pulsar 应用场景运维供给参阅。

当然,咱们对 Pulsar 集群的调优不会停止,也会继续深入并参加社区项目共建。

因为单个 Topic 对应的客户端比较多,每个客户端所在的 Pod、Client 内部会针对每个 Topic 创立许多的出产者和顾客。由此就对 Pulsar SDK 在断连、重连、出产等细节的处理方面的要求比较高,对各种细节处理流程都会十分的灵敏。SDK 内部处理比较粗糙的当地会导致大面积的重连,从而影响出产和消费。现在,Pulsar Go SDK 在许多细节方面处理不行细腻,与 Pulsar Java SDK 的处理有许多不一样的当地,需求继续优化和完善。腾讯 TEG 数据渠道 MQ 团队也在积极参加到社区,与社区共建逐步完善 Go SDK 版别。

别的,针对腾讯 Data 项意图特大规模和事务特色,Broker 端需求处理许多的元数据信息,后续 Broker 本身的装备仍需求做部分的装备和继续调整。一同,咱们除了扩容机器资源外,还计划在 Apache Pulsar 的读/写线程数、Entry 缓存巨细、Bookie 读/写 Cache 装备、Bookie 读写线程数等装备方面做进一步的调优处理。