本期分享嘉宾:潘天颖,来自涂鸦智能 OC 支撑平台。开源爱好者,Apache  Dubbo-Go committer、Pulsar 用户。

关于涂鸦智能

涂鸦智能是一个全球化智能平台和“AI+IoT”开发者平台,也是世界排名前列的语音 AI 交互平台。连接消费者、制作品牌、OEM 厂商和零售连锁的智能化需求,为客户提供一站式人工智能物联网的解决方案。

并且涵盖了硬件介入、云服务以及 APP 软件开发三方面,形成人工智能+制造业的服务闭环,为消费类 IoT 智能设备提供 B 端技术及商业模式升级服务,从而满足消费者对硬件产品更高的诉求。

在涂鸦智能的产品中,需求量较大的功能则是消息队列的传输。而消息队列的目的,就是往云端上传一些队列消息,基于平台作为一个中间件,推给第三方(开发者、用户等)。

所以「消息队列推送」一直涂鸦智能的痛点,而后在经过一些调研,选择使用 Pulsar 进行更新迭代 。


为什么选择 Pulsar

现状及痛点

在没使用 Pulsar 之前,涂鸦使用的架构基本如下图所示。消息进入接入层后,通过 Kafka进行消息分发转化,这个消息集群主要在做一些消息分发和路由的功能。之后再通过 HTTP 投递给第三方。

以上的架构模式存在一些业务痛点:

1. HTTP 投递方式不灵活,容易丢消息

基于网络原因、公司服务器规模不足以支撑业务时,都有可能出现重启过程中消息丢失的现象。如果想要满足这个需求,就需要对消息的持久化进行额外的处理。

2. Kafka topic 数量与日俱增,运维成本高

随着接入厂家和开发者数量的增加,导致 Kafka 的运维层面压力会比较大,人力和时间等耗费比较高。

3. Kafka 自身的一些痛点,比如 Rebalance 机制

业务集群需要经常升级,consumer 就会经常断连。断连情况下,Rebalance 的过程是很长的,导致消息堆积量加大,造成用户体验下降。同时堆积后的重启,在大集群量情况下,对消费端的压力会非常大。 

4. 租户之间会相互影响

如果有一个租户挂掉并且没有进行及时处理,就会一直堆积在 Kafka 的处理器上,耽误后续进程,降低消息上报性能,影响到其他租户。

Pulsar 的特性与优势 

Apache Pulsar 是灵活的发布-订阅消息系统,采用分层分片架构。 

1. 丰富的投递/订阅策略

Pulsar 做了队列模型和流模型的统一,在 Topic 级别只需保存一份数据,同一份数据可多次消费。以流式、队列等方式计算不同的订阅模型大大提升了灵活度。

玩转 Dubbo-go & Pulsar_队列


2. 运维难度小(相比 Kafka),Rebalance 机制反应迅速

主要体现在跨地域复制方面。Pulsar 使用计算与存储分离的云原生架构,数据从 Broker 搬离,存在共享存储内部。上层是无状态 Broker,复制消息分发和服务;下层是持久化的存储层 Bookie 集群。

Pulsar 存储是分片的,这种架构可以避免扩容时受限制,实现数据的独立扩展和快速恢复。

3. 多租户隔离优势

租户和命名空间(namespace)是 Pulsar 支持多租户的两个核心概念。

  • 在租户级别,Pulsar 为特定的租户预留合适的存储空间、应用授权与认证机制。
  • 在命名空间级别,Pulsar 有一系列的配置策略(policy),包括存储配额、流控、消息过期策略和命名空间之间的隔离策略。

现阶段结构 

刚好这三点特性,对应了之前涂鸦面临的痛点,所以在契合下开始转向使用 Pulsar 来替代了 Kafka。

玩转 Dubbo-go & Pulsar_人工智能_02

目前 Pulsar 的架构已应用到涂鸦智能平台,成为一个主导消息队列,后续也在围绕 Pulsar 进行一些二次开发和周边服务搭建。

以前信息的投递会有 5-6 s 的延迟,现在大概只有 1 s,整体的提升和改进是非常大的。

当然用 Pulsar 替代 Kafka 的过程,也有一些缺点,比如:成本高。这个过程就需要督促第三方开发者去替换 SDK,同时过渡时期还要支持两套系统。

刚好最近 StreamNative 开源了 KoP,可以让两者之间的迁移更简单,也算解决了这一问题。

玩转 Dubbo-go & Pulsar_运维_03

上图就是 BookKeeper 内的 Pulsar 架构示意图,其中 zk 是指 ZooKeeper。更多关于 Broker、Bookie 和 Proxy 等概念介绍,可以参考之前 TGIP-CN 的回顾:​​Message Lifecycle:Pulsar 里的信息传递究竟是什么样子​​。

同时借由存储端 BookKeeper 的存储中间件特性,使得 Pulsar 现在的存储分离架构并没有增加额外的使用复杂度。

Proxy 在这里提供了类似 TCP 的一个代理,为 Consume 提供了“寻址”的功能。Consumer 无需关心真实的 Broker 地址,连上 Proxy 后会直接从 ZooKeeper 里拉取 Topic 的位置等数据,此过程中 Consumer 只需保证稳定的连接即可。

但 Proxy 并没有进行负载均衡的功能,这些都是在 Broker 上进行的。这一点也在之前的 TGIP-CN 直播中提到过。

当然针对涂鸦的一些使用场景,他们也在 Proxy 上进行了一些扩展。


Dubbo-go + Pulsar 的实例应用

玩转 Dubbo-go & Pulsar_队列_04

上图是一开始使用 Pulsar 时的架构图。生产者投递消息后,利用 in Topic 路由解析出来并进行投递。但是这个过程中需要构建多个 Pulsar 集群,导致运维程度的增加。

玩转 Dubbo-go & Pulsar_大数据_05

现在在 Pulsar 架构里增加一个“source”,它可以用来收集之前的 topic,搭配 function 功能进行传递。

之后在 function 部件内嵌入了 Dubbo-go consumer,把一些复杂的路由规则通过 Dubbo-go  consumer 进行拉取。同时借用 Pulsar broker 的整体集群管理,减少了运维的业务压力。

玩转 Dubbo-go & Pulsar_运维_06

Dubbo-go

具体关于 Dubbo 的一些 demo 展示或者使用方法,可以参考以下网站。

  • Dubbo 中文网站:
    http://dubbo.apache.org/zh-cn/

  • GitHub 仓库:
    https://github.com/apache/dubbo-go

Dubbo-go 的架构示意图可以参考下方:

玩转 Dubbo-go & Pulsar_java_07

玩转 Dubbo-go & Pulsar_队列_08