前言
本文将介绍 pulsar 的核心功能,不会对设计细节以及与其他 MQ 进行对比
概述
Apache Pulsar 是一个多租户、高性能的发布-订阅消息中间件, Pulsar 最初由雅虎开发。从 2018 年 9 月以来,它是 Apache 基金会的顶级项目之一,由 Apache 软件基金会管理。更多历史背景参考 。截止当前发文, 项目仓库 已有 9.7k 个 star 和 451 位 contributions,目前最新版本为 2.8.1
和大多数消息中间件一样,Pulsar 也是建立在发布订阅模式上。在这种模式中,producer 向 broker 中的 topic 发送 message。consumer 订阅这些 topic 并处理传入的消息。不同之处在于 pulsar 中的 broker 不会物理存储 message,而是交给 apache bookkeeper 单独处理,broker 只是充当一个消息路由寻址的功能
架构
从宏观角度来看,多个 Broker 节点组成一个 Pulsar Cluster;多个 Pulsar Cluster 组成一个 Pulsar Instance,Pulsar 通过 geo-replication 支持 Pulsar Instance 内在不同的集群发送和消费消息。在 pulsar 集群中:
- 每个 Broker 节点处理和负载均衡来自 Producer 发送的 Message ,将 Message 分派给消费者,与 Pulsar 配置存储 Zookeeper 通信以处理各种协调任务,将消息存储在 BookKeeper 实例(又名 bookies)中,依赖特定于集群的 ZooKeeper 集群任务等
- BookKeeper 集群处理 Message 的持久存储
- ZooKeeper 集群处理 Pulsar 集群之间的协调任务(localZK 负责 cluster 内部配置,Global ZK 负责 Cluster 之间的配置)
- Global replication 负责集群间的数据复制
核心概念
Broker
Pulsar 中的 broker 是一个无状态的组件,主要负责两部分:
- 一个提供 REST 接口的 HTTP 服务器 ,为 Producter 和 Consumer 提供了 tencent、namespace、topic 、subscription 管理和 topic 寻址的功能。Producter 连接到 Broker 发布消息, Consumer 连接到 Broker 来消费消息
- 一个基于 TCP 协议的异步协调器,用于所有的数据传输
Producer
Producer 发送 Message 到 Topic 时,除了支持 sync、async 的发送方式之外,在与 Topic 连接上, 还增加了 Excusive、Share、WaitForExclusive 三种语义:
Access mode | Description |
---|---|
Share | 共享模式,所有 producer 可同时使用同一个 topic(默认策略) |
Excusive | 独占模式,只会有一个 producer 向生产者发送消息,确保当有一个 producer 与 topic 建立好连接之后,其他 producer 发送消息时将报错 |
WaitForExclusive | 主备模式,与 topic 连接成功的 producer 将成为 leader producer,其他 producer 连接时将会阻塞等待(不会超时),直到 leader producer 断开连接 |
Consumer
Consumer 通过 subscription 来连接到 Topic,每次通过发送 flow permit request 给 Broker 来获取 Message,同时将 Message 放入本地维护的一个 buffer queue (默认大小为 1000)队列来缓冲,每次 consumer.receive() 调用时,将从 buffer queue 获取消息
类似的, consumer 也支持两个接收消息的方式:sync、async
Receive Mode | Description |
---|---|
Sync receive | 阻塞等待,直到有 Message 可用 |
Async receive | 返回一个 future , 将 Message 是否可用通过 future 中的状态来维护 |
Topic
Topic 在 pulsar 中被当做是一个渠道来传输 Producer 和 Conusmer 之间的消息。一个完整的 Topic 结构为:{persistent|non-persistent}//tenant/namespace/topic
由 4 部分构成:
component | desc | |
---|---|---|
1 | {persistent|non-persistent} | pulsar 支持持久化、和非持久化的 Topic,persistent、non-persistent 分别对应这两种;对于持久化 Topic 来讲,所有的消息都会被持久化到磁盘中,如果是 cluster 集群则会持久化到多个 pulsar 实例的磁盘中,如果是非持久话的 Topic,则只会将消息保存到内存中,而不会持久化到磁盘 |
2 | tenant | 租户,Topic 中最上层的管理者,属于 puslar 实例层级 |
3 | namespace | 命名空间,Topic 最小的管理单元,大多数 Topic 的配置管理都跟 namespace 有关,每个租户 tenant 都拥有至少一个 namespace |
4 | topic | topic 即与其他消息中间件类似的 topic name,在 pulsar 中没有实际的意义 |
Subscription
每条消息在消息的日志上都有一个偏移量 (offset),Pulsar 使用 Subscrtion 来跟踪这个偏移量(offset),通过 Subscrtion 可以控制 Consumer 消费消息的方式,在 pulsar 中提供了四种消费方式: exclusive 、shared、 failover, and key_shared.
Exclusive
即独占模式,在独占模式下,只允许一个 consumer 连接到 Subscription 上。如果多个 consumer 使用同一个 Subscription 订阅一个 Topic ,则会发生错误
Shared
共享模式,允许多个 consumer 使用同一个 Subscription 订阅 Topic,Message 将会循环的发给多个 Consumer,
Failover
key_shared
按 key 共享,与 Shared 模式相同,允许使用同一个 Subscription 订阅 Topic,不同的是 Message 在 Consumer 的消费中,具有相同 key 或 orderingKey 的 Message 只传递给同一个 Consumer。无论消息被重新传递多少次,它都会传递给同一个消费者(必须指定 orderingKey 或 key)
Partitioned topics
普通的 Topic 仅由一个 Broker 处理,但单个 Broker 处理瓶颈将限制 Topic 的最大吞吐量,Partitioned Topic 分区主题通过多 Broker 并发处理来提高了 Topic 的吞吐量.
分区主题实际上在 pulsar 中是由多个内部主题构成,每个主题归属于某一个 Broker 上,message 和对应 broker 上的内部主题路由由 pulsar 来维护
Topic1 主题有五个分区(P0 到 P4),分布在三个 Broker 上。因为分区比 Broker 多,两个 Broker 一个处理两个分区,而第三个只处理一个(同样,Pulsar 会自动处理这种分区的分布)
通常将 producer 发送 message 到 parition topic 的消息路由方式和消费者通过 Subscription 订阅 Topic 分开讨论,分区消息路由方式决定了吞吐量的高低;而 consumer 通过 subscription 订阅消费者则由应用程序业务来决定
分区主题和普通主题在 Subscription 一个 Topic 上没有区别,,因为分区仅仅决定消息从生产者发布到消费者处理和 ACK 确认之间逻辑
Routing Mode
Mode | Description |
---|---|
RoundRobinPatition | 如果 Message 中没有 key 属性,那么 producer 将以循环方式跨所有分区发送消息,最终可以达到最大吞吐量,如果在 Message 上指定了 Key,则 producer 将 key hash 之后,将 Message 分配给特定分区。(默认处理方式) |
SinglePartition | 如果 Message 中没有 key 属性,那么 producer 将随机选择一个分区并将所有消息发布到该分区中,如果在 Message 上指定了 Key,则 producer 将 key hash 之后,将 Message 分配给特定分区。 |
CustomPartition | 使用将被调用的自定义消息路由器实现来确定特定消息的分区 |
Ordering guarantee
消息的顺序与消息路由模式和消息的 key 有关,通常需要保证具有相同 key 的消息在同一个 topic 中具有顺序性。如果消息中带有 key 属性,那么这个消息在 RoundRobinPatition 和 SinglePartition 路由模式中将具有顺序性
总结
通过对 Pulsar 组成的一些功能模块进行简单介绍来大致了解其是如何运转的(producer->broker->consumer)、由那些组件构成的(pulsar-instance、zookeeper、bookker),以及有哪些功能特性(route mode、subscription、partition ),后面将通过源码层来深度对一些优秀的设计进行剖析