乐趣区

关于消息队列:最佳实践|Apache-Pulsar-在华为云物联网之旅

对于 Apache Pulsar

Apache Pulsar 是 Apache 软件基金会顶级我的项目,是下一代云原生分布式音讯流平台,集音讯、存储、轻量化函数式计算为一体,采纳计算与存储拆散架构设计,反对多租户、长久化存储、多机房跨区域数据复制,具备强一致性、高吞吐、低延时及高可扩展性等流数据存储个性。

GitHub 地址:http://github.com/apache/pulsar/

设施接入服务(IoTDA)是华为云物联网平台的外围服务,IoTDA 须要一款牢靠的消息中间件,通过比照多款消息中间件的能力与个性,Apache Pulsar 凭借其多租户设计、计算与存储拆散架构、反对 Key_Shared 模式生产等个性成为华为云物联网消息中间件的首选。本文介绍了 Pulsar 在华为云物联网的上线历程以及上线过程中遇到的问题和相应的解决方案。

华为云设施接入服务介绍

设施接入服务(IoTDA)具备海量设施连贯上云、设施和云端双向音讯通信、数据流转、批量设施治理、近程管制和监控、OTA 降级、设施联动规定等能力。下图为华为云物联网架构图,下层为物联网利用,包含车联网、智慧城市、智慧园区等。设施层通过直连网关、边缘网络连接到物联网平台。目前华为云物联网联接数超过 3 亿,IoT 平台竞争力中国第一。

数据流转指用户在物联网平台设置规定后,当设施行为满足规定条件时,平台会触发相应的规定动作来实现用户需要,例如对接到华为云其余服务,提供存储、计算、剖析设施数据的全栈服务,如 DIS、Kafka、OBS、InfluxDb 等,也能够通过其余通信协议和客户的零碎对接,如 HTTP、AMQP。在这些动作中,物联网平台次要做客户端或服务端。
依据用户类别,能够将应用场景分为三类:

  • 体量较大的客户个别会抉择推送到消息中间件(如 Pulsar、Kafka)上,并在云上构建本人的业务零碎进行生产解决。
  • 中长尾客户通常会抉择将数据推送到本人的数据库(如 MySQL)中进行解决,或由本人的 HTTP 服务器接收数据进行解决。
  • 更轻量级的客户会抉择通过 AMQP 协定创立简略的客户端进行连贯。

原推送模块的痛点

原推送模块采纳 Apache Kafka 计划,这种运行模式自身有一些弊病,且扩容操作简单,为开发和运维团队带来累赘。此外,原推送模块反对客户端类型和服务端类型的推送,但不反对 AMQP 推送,其架构图如下。Consumer 一直从 Kafka 中拉取音讯,并将发送失败的音讯存入数据库,期待重试。这种运行模式带来了很多问题:

  • 即便很多客户的服务器不可达,consumer 仍须要从 Kafka 拉取音讯(因为 Kafka 只有一个 topic)并尝试发送。
  • 无奈依据单用户来配置音讯的存储工夫和大小。
  • 有些客户的服务器能力差,无法控制将音讯推送到单个客户的速率。

Topic 数量

2020 年 5 月,为晋升产品的竞争力,咱们打算让客户通过 AMQP 协定来接管流转数据。AMQP 协定的客户端接入更加简单,而客户可能会将 AMQP 客户端集成在手机端,每天定时上线两小时,这种状况下,咱们须要保障客户在应用时不会呈现数据失落,因而要求消息中间件反对多于规定数量的 topic(有些客户单规定下数据量大,单 topic 无奈撑持)。目前,咱们的规定数量已超过 3 万,预计很快会达到 5 万,并且还会持续增长。

Kafka topic 在底层占用文件句柄,且共享 OS 缓存,无奈反对量级较大的 topic,友商的 Kafka 最多能够撑持 1800 个 topic。咱们要想反对规定数量级别的队列,就必须保护多个 Kafka 集群,下图是咱们基于 Kafka 设计的计划。

基于 Kafka 计划的实现会非常复杂,咱们岂但要保护多个 Kafka 集群的生命周期,还要保护租户和 Kafka 集群之间的映射关系,因为 Kafka 不反对 Shared 生产模型,还须要两层中继。另外,如果某个 Kafka 集群上 topic 数量已达到下限,但因为流转数据过多,须要对 topic 进行扩容。在这种状况下,不迁徙数据就无奈对原有集群进行扩容。整体计划非常复杂,对开发和运维都是很大的挑战。

为什么抉择 Pulsar

为了解决咱们在 Kafka 计划中的问题,咱们开始调研市面上风行的消息中间件,理解到 Apache Pulsar。Apache Pulsar 是云原生的分布式消息传递和流平台,原生反对诸多优良个性,其独有 Key_Shared 模式和百万 topic 反对是咱们迫切需要的个性。

  • Pulsar 反对 Key_Shared 模式。如果 Pulsar 的单个分片反对 3000 QPS,而客户的一个 AMQP 客户端只反对 300 QPS。这种状况下,最佳解决方案是应用 Pulsar 的共享模式,启用多客户端连贯,即同时连贯 10 个客户端来解决数据。如果应用 Failover 模式,则须要扩到 10 个 partition,造成资源的节约。
  • Pulsar 可扩大至百万级 topic。咱们能够将一个规定对应于一个 Pulsar topic。AMQP 客户端上线时,即可从上一次生产到的地位开始读取,保障不丢音讯。

Pulsar 是基于云上的多租户设计,而 Kafka 更偏差于在零碎和零碎之间对接,单租户、高吞吐。Pulsar 思考了基于 K8s 的部署,整体部署易实现;Pulsar 的计算与存储拆散,扩容操作简略,扩容时 topic 中断工夫短,重试可实现业务无中断;并且反对共享订阅类型,更灵便。咱们从不同维度对 Pulsar 和 Kafka 做了比照,后果如下:

Pulsar 不仅可能解决 Kafka 计划的有余,其不丢音讯的个性更是完满符合了咱们的需要,所以咱们决定试用 Pulsar。

初版设计

最后设计时,咱们想在客户端类型和服务端类型都应用 Key_Shared 生产模式。下图为客户端类型(以 HTTP 为例)的设计,客户每配置一条数据流转规定,咱们就在 Pulsar 中创立一个 topic,consumer 生产 topic,再通过 NAT 网关推送到客户的 HTTP 服务器。

服务端类型(以 AMQP 为例)推送的设计如下图。如果没有连贯到 AMQP 客户端,即便启动 consumer 拉取到数据,也无奈进行下一步解决,所以当客户端通过负载平衡组件连贯到对应的 consumer 微服务实例后,该实例才会启动对应 topic 的 consumer 进行生产。一个 AMQP 的连贯对应一个 consumer。

Pulsar 集群内 topic 单 partition 吞吐量无限,当单个客户的规定数据量超过吞吐量时,比方当 topic 的性能规格在 3000 左右,而客户的预估业务量为 5000 时,咱们须要为 topic 扩容 partition。为了防止重启 producer/consumer,咱们将 autoUpdatePartition 参数设置为 true,使 producer/consumer 能够动静感知到 partition 的变动。

初版设计在测试中遇到的问题

在对初版设计方案进行测试时,咱们发现这一计划存在一些问题,次要体现在以下三个方面:

  • 客户端类型推送应用上述设计,微服务实例和 consumer 之间造成了网状关系。假如咱们有 1 万个客户规定和 4 个微服务实例,则会有 4 万个生产 - 订阅关系。单个微服务实例在内存中同时有 1 万个 consumer,consumer 接管队列大小是吞吐量和内存耗费的要害,但不易配置。若配置偏大,则在异样场景下,consumer 发送不出 HTTP 音讯,会造成大量音讯积压在 consumer 中,导致 consumer 内存溢出。假如有 1000 个 consumer,网络突然断开 5 分钟,则这 5 分钟内的音讯都会积压在接管队列中;若配置偏小,consumer 与服务器之间通信的效率较低,影响零碎性能。
  • 在 Pulsar 或生产生产服务滚动降级的场景中,频繁申请 topic 元数据对集群压力较大(申请个数为实例个数与 topic 数量的乘积)。
  • autoUpdatePartition 对系统资源影响大。如果每个 topic 都开启 autoUpdatePartition,依照默认设置,每个 topic 每分钟发送一次 ZooKeeper 申请。

咱们在 Pulsar 社区反馈了这个问题,StreamNative 团队同学给了大力支持和帮忙,倡议咱们对客户进行分组后再依据须要设置 autoUpdatePartition 参数。有了社区强有力的反对,咱们决定做相应改良后开始策动上线计划。

上线计划

咱们的客户大抵分为两种,一种是在业务忙时有大量数据上行的推送忙碌用户,其特点是一个分片可能满足不了诉求,用户数量少;另一种是业务比较稳定,数据量中等,其特点是一个分片足够,用户数量多。

咱们依据倡议对用户进行分组,独自部署推送忙碌用户的工作负载,合设业务量中等的用户。目前,咱们依据客户的业务容量,通过 SRE 在配置核心手动分组,将来会依据实时统计数据主动分组。对业务进行分组不仅能够大大减少 topic 和 consumer 之间的组合数量,也升高了重启时申请元数据的次数。另外,两类用户客户端参数在分组后也不完全相同,首先,autoUpdatePartition 仅在忙碌用户 topic 中开启;其次,两组工作负载的接管队列大小不同。

部署

咱们采纳容器化部署形式为两类用户部署:应用 deployment 形式部署 broker,StatefulSet 形式部署 BookKeeper 和 ZooKeeper。部署场景包含云端部署和边缘部署,不同的部署形式对可靠性、性能要求不同,咱们设置的部署参数如下:

在部署时,咱们发现:

  • topic 之间 EnsembleSize 和 Write Quorum Size(Qw)参数雷同时,写入性能最好。
  • 云端音讯量大,如果正本数量为 2,则要冗余 100% 部署,正本数量为 3 时只需冗余 50%。

Pulsar 调优计划

上述计划已在半年前顺利上线,并且咱们还在测试环境中测试了 5 万 topic,10 万音讯每秒的场景,测试期间遇到了一些问题,并依据具体情况采取了调优计划,详情参阅 Pulsar 5 万 topic 调优。本节重点介绍提早、端口和改良倡议。

降低生产 / 生产提早

通过应用测试工具,咱们发现音讯的整体端到端提早较大。

为了不便定位问题,咱们开发了单 topic debug 个性。在海量音讯场景下,无论是测试环境还是生产环境,都不会轻易在 broker 开启全局 debug。咱们在配置核心减少了一个配置,只为配置列表中的 topic 打印具体的 debug 信息。在单 topic debug 个性的配合下,咱们很快发现音讯的最大提早呈现在 producer 发送音讯后与服务端接管到音讯之间,可能的起因是 netty 线程数配置偏小。

但减少 netty 线程数并没有齐全解决这一问题,咱们发现单 jvm 实例仍会呈现性能瓶颈,上文提到按用户的数据量大小分组后,小用户组须要服务大概四万个 topic,因为须要启动雷同数量级的 consumer,导致启动慢(进而导致降级时中断工夫长)、内存队列有余、调度简单等。咱们最初决定再对小用户组进行哈希分组,每个实例负责约 1 万个 consumer,顺利解决了生产生产提早大的问题。

采纳 8080 端口连贯 broker

咱们采纳 8080 端口而非 6650 端口连贯 broker,起因次要有两点:

  • 日志具体,而且大部分发向 8080 的申请是元数据申请,有助于排查问题,易监控。比方,jetty 的 requestLog 很容易监测到创立 topic 失败、创立 producer 超时等事件。
  • 能够隔离数据申请和元数据申请,防止在 6650 端口忙碌时影响创立 topic、删除 topic 等操作。

和 6650 端口相比,8080 端口效率性能较差。在 5 万 topic 量级下,降级 producer/consumer 或 broker 时,须要创立大量的 producer/consumer,对 8080 端口产生大量申请,如 partitions、lookup 申请。咱们通过减少 Pulsar 中 jetty 线程数,顺利解决了这一问题。

改良倡议

Pulsar 在运维和应答问题方面能力稍有欠缺,咱们心愿 Pulsar 能在以下几个方面有所改进:

  • 主动调整客户端参数,如发送队列大小、接管队列大小等,这样应用万级 topic 时会更加晦涩。
  • 在遇到到不可复原的谬误(如操作 ZooKeeper 失败)时,裸露 API 接口,使咱们能够轻松对接到云上的告警平台。
  • 在运行期间通过日志追踪单个 topic,反对运维人员应用 kibana 工具联合业务日志疾速定位、解决问题。
  • 采样追踪 Pulsar 外部生产、生产、存储的要害节点,并将数据导出到 APM 零碎(如 Skywalking),更易分析优化性能。
  • 在负载平衡策略中思考 topic 数量。
  • BookKeeper 监控时只监控了 data 盘的使用率,没有监控 journal 盘的使用率。

结语

从首次接触 Pulsar 到设计上线,咱们一共用了三四个月的工夫。上线后,Pulsar 始终运行稳固、性能良好,帮忙咱们实现了预期指标。Pulsar 大大简化了华为云物联网平台数据接入服务的整体架构,安稳低提早地撑持着咱们的新业务,因而咱们能够专一于晋升业务竞争力。因为 Pulsar 的优良性能,咱们也将其利用于数据分析服务,并且心愿能够在业务中应用 Pulsar Functions,进一步晋升产品竞争力。

作者简介

张俭:华为云 IoT 高级工程师。关注云原生、IoT、消息中间件、APM。

相干浏览

  • 最佳实际|Apache Pulsar 在拉卡拉的技术实际
  • Apache Pulsar 在 EMQ 物联网平台产品 ActorCloud 上的利用
  • Apache Pulsar 在能源互联网畛域的落地实际

退出移动版