- 消息队列
- 后端
- 流处理
【免费下载链接】pulsar
Apache Pulsar - distributed pub-sub messaging system
Apache Pulsar 2.0 是一次带来重大变更的主版本发布,其中最直接影响日常使用的,是"property(属性)"术语被"tenant(租户)"取代、Topic 全名中的 cluster 组件被移除,以及随之而来的灵活(shorthand)命名规则。本文以 2.3.2 版本文档为主体,结合仓库中 TopicName.java 等源码实现,系统梳理这些变更的来龙去脉、新旧格式的兼容机制与底层解析逻辑,帮助你在升级或新建集群时正确书写 Topic 名称、使用管理命令,并理解旧集群数据为何无需迁移即可继续访问。
Pulsar 2.0 的新特性与重大变更概览
Pulsar 2.0 对平台做了若干"大胆的"(bold)改变,除了引入新特性之外,还包含可能显著影响日常使用的重大变更。变更概览如下表:
| 特性 / 变更 | 说明 |
|---|---|
| Pulsar Functions | 面向 Pulsar 的轻量级计算(lightweight compute)能力,作为 2.0 新特性加入 |
| Properties → Tenants | 统一术语,property更名为tenant,管理接口随之调整 |
| Topic 命名简化 | 移除 Topic 全名中的 cluster 组件,引入默认值驱动的灵活命名 |
| 其它术语调整 | 部分场景仍保留旧术语,但已标记为 deprecated,将在未来版本彻底移除 |
其中 Pulsar Functions 允许直接在 Pulsar 集群内运行无状态、轻量级的处理逻辑(如bin/pulsar-admin functions create命令),本文不展开其细节,重点聚焦命名体系的两项重大变更。
重大变更一:Properties 与 Tenants 的术语统一
在 2.0 之前,Pulsar 使用property(属性)概念作为多租户隔离的基本单位。从 2.0 开始,"property" 术语被移除,因为property 与 tenant 本质上就是同一个东西,统一为tenant(租户)可以显著降低认知成本。
管理接口的对应变化
命令行管理接口是变化最直观的体现:原先的pulsar-admin properties接口被pulsar-admin tenants接口取代。以 2.3.2 版本仓库中的 reference-pulsar-admin.md 为据,tenants命令的用法与子命令如下:
$ pulsar-admin tenants subcommand支持的子命令包括:
list:列出当前实例中已有的租户get:获取某个租户的配置create:创建新租户update:更新租户配置delete:删除租户
例如,查看 admin-api-tenants.md 中的创建示例:
$ pulsar-admin tenants create my-tenant对应的 REST API 为GET /admin/v2/tenants等/admin/v2路径下的接口,Java 客户端则对应admin.tenants().getTenants()一类方法调用。
源码中的术语残留
从源码结构看,虽然 2.0 已将术语统一为 tenant,但在个别底层 API 中仍能看到旧时代痕迹。例如 TopicName.java 中的getCluster()方法被标注了@Deprecated,并在注释中说明其仅在旧命名格式下有意义(旧格式persistent://tenant/cluster/namespace/topic包含 cluster 段,而新格式persistent://tenant/namespace/topic没有)。这印证了原文档"部分场景仍使用旧术语、但已弃用并将在未来版本移除"的说明——在代码层面,cluster 字段在新命名下为null。
重大变更二:Topic 命名规则重构
2.0 之前的完整 Topic 名格式
在 2.0 之前,所有Pulsar Topic 的名称都具有如下形式:
{persistent|non-persistent}://property/cluster/namespace/topic即四个组成部分:Topic 类型(持久化/非持久化)、property、cluster、namespace 和 Topic 名。这种格式要求使用者时刻关心 Topic 属于哪个集群,在跨集群部署和客户端连接时容易写错。
2.0 的 Topic 命名变化
Pulsar 2.0 对 Topic 命名做出了如下核心调整:
- 不再有 cluster 组件(见下文"移除 Cluster 组件")
- property 更名为 tenant(见上文)
- 引入灵活(flexible)命名系统,很多场景下可以使用更短的名称
/(斜杠)不允许出现在 Topic 名称中——因为斜杠是各段之间的分隔符,TopicName.java 的解析逻辑正是按/切分来识别 tenant、namespace 与 localName 的,Topic 名(localName)本身若含斜杠将破坏结构
移除 Cluster 组件
cluster 组件从 Topic 全名中移除后,所有 Topic 名称的新形式为:
{persistent|non-persistent}://tenant/namespace/topic使用旧格式命名、已经存在的 Topic 将继续正常工作,无需任何修改,官方也没有改变这一兼容策略的计划。这意味着存量集群可以平滑过渡到 2.0,无需迁移数据或改名。
源码中的新旧格式共存逻辑
新旧两种格式之所以能共存,关键在 TopicName.java 的构造函数解析逻辑。其核心思路是:
- 若名称不含
://,视为短名(short name),按段数补全:1 段补全为persistent://public/default/<topic>,3 段补全为persistent://<tenant>/<namespace>/<topic>,其余情况报IllegalArgumentException; - 若含
://,对://之后的剩余部分按/切分:3 段(tenant/namespace/<localName>)判定为新格式(V2),此时cluster = null;4 段(tenant/cluster/namespace/<localName>)判定为旧格式(legacy),保留 cluster; - isV2() 的实现即为
return cluster == null,一目了然。
TopicDomain 枚举同样只保留两种合法类型,定义于 TopicDomain.java:
public enum TopicDomain { persistent("persistent"), non_persistent("non-persistent"); ... }客户端侧对非法名称的拦截也依赖这套解析:例如 PulsarClientImpl.java 在创建 producer/consumer 前调用TopicName.isValid(topic),校验失败即抛异常,从源头保证写入的 Topic 名必然符合上述规则。
灵活(Flexible)Topic 命名与默认值
新命名系统之所以"灵活",是因为 2.0 引入了默认的 Topic 类型、默认租户与默认命名空间:
| Topic 要素 | 默认值 |
|---|---|
| topic 类型 | persistent |
| tenant | public |
| namespace | default |
下表给出利用隐式默认值进行名称"翻译"的示例:
| 输入的 Topic 名 | 翻译后的完整 Topic 名 |
|---|---|
my-topic | persistent://public/default/my-topic |
my-tenant/my-namespace/my-topic | persistent://my-tenant/my-namespace/my-topic |
这两个翻译结果与 TopicName.java 中短名补全逻辑的产出完全一致:my-topic只有 1 段,补上PUBLIC_TENANT("public")与DEFAULT_NAMESPACE("default");my-tenant/my-namespace/my-topic有 3 段,直接补上persistent://前缀。仓库中大量示例也直接使用这种简写,例如 client-libraries-java.md 中的.topic("my-topic")与 functions-overview.md 中--inputs persistent://public/default/sentences的完整写法并存。
非持久化 Topic 的例外:必须使用完整名称
对于非持久化 Topic(non-persistent topics),你必须继续写全整个 Topic 名称,因为持久化 Topic 的默认值补全规则不适用于非持久化 Topic。因此你不能使用
non-persistent://my-topic这样的简写,而必须写成non-persistent://public/default/my-topic。
这一约束同样能在源码中找到依据:短名补全逻辑(TopicName.java)对不含://的名称一律按persistent类型补全,TopicDomain.persistent是唯一的隐式默认;一旦你显式写出non-persistent://前缀,就必须同时给出 tenant 与 namespace 两段,否则 3 段/1 段之外的切分结果会直接抛出IllegalArgumentException。
关于非持久化 Topic 的更多背景,可参考 concepts-messaging.md 中的说明:其消息只存于内存、不落盘 BookKeeper,broker 故障或订阅者断开会导致在途消息丢失,且其名称形式为non-persistent://tenant/namespace/topic,因此使用前务必确认场景能容忍消息丢失。
从源码看 Topic 名的规范化与内部表示
理解了新旧格式后,再深入一步:TopicName对象不仅是字符串解析结果,还是路由、持久化与查找的关键标识。
名称归一化与缓存
TopicName.java 使用 GuavaLoadingCache(最大 10 万条、30 分钟无访问过期)缓存解析结果,所有TopicName.get(...)调用都经过缓存,避免高频创建 producer/consumer 时反复解析字符串。构造函数(L110-L185)在完成段切分后,会根据isV2()的结果把completeTopicName重写为标准形式:
- V2 格式:
%s://%s/%s/%s(domain/tenant/namespace/localName) - 旧格式:
%s://%s/%s/%s/%s(domain/tenant/cluster/namespace/localName)
也就是说,即使你传入的是my-topic短名,最终得到的TopicName.toString()也是完整的persistent://public/default/my-topic。
不同场景下的序列化形式
同一个TopicName对象在不同场景下会输出不同的路径形式:
getRestPath()(L307-L318):供管理 Web 服务使用的 REST 路径,如persistent/my-tenant/my-namespace/my-topic(注意://变成了/);getLookupName()(L348-L354):用于 Topic 查找(lookup),如persistent/my-tenant/my-namespace/my-topic;getPersistenceNamingEncoding()(L325-L336):持久化资源的相对路径,按tenant/namespace/domain/topic顺序组织,将 domain 也作为路径段之一。
无论哪种形式,V2 与 legacy 的差别始终体现在"是否包含 cluster 段"上,这与原文档描述的命名变化完全吻合。
分区 Topic 的命名约定
虽然原文档未展开,但命名规则还隐含了分区 Topic 的约定:PARTITIONED_TOPIC_SUFFIX 为-partition-,第 N 个分区的名称为<topic>-partition-<N>(L237-L243),getPartitionedTopicName()则负责从分区名还原出基础 Topic 名。书写或解析名称时需留意这一后缀保留在 localName 中。
迁移与实战建议
综合原文档与仓库现状,给出以下实操要点:
- 旧集群无需迁移:采用
persistent://tenant/cluster/namespace/topic旧格式的存量 Topic 会继续工作,官方无变更计划,可放心升级。 - 新代码一律使用新格式:新建 Topic 时推荐写全
persistent://<tenant>/<namespace>/<topic>(或non-persistent://...),避免歧义;仅在明确依赖默认值时可使用my-topic这类短名。 - 非持久化 Topic 必须写全名:
non-persistent://public/default/my-topic,不能使用non-persistent://my-topic简写。 - 管理命令使用 tenants:统一使用
bin/pulsar-admin tenants create/list/get/update/delete,不要再使用properties系列命令。 - 注意名称合法性:localName 中不要出现
/,否则会被解析器当作段分隔符并导致IllegalArgumentException;客户端在创建 producer/consumer 前即会通过TopicName.isValid拦截非法名称。
如果需要验证客户端 API 中短名与完整名的实际用法,可在 client-libraries-java.md、client-libraries-cpp.md 等文档中查看.topic("my-topic")形式的示例;需要确认租户管理命令的完整参数,可继续阅读 admin-api-tenants.md 与 reference-pulsar-admin.md。
小结
Pulsar 2.0 通过"property→tenant"术语统一与 Topic 命名去 cluster 化,显著降低了多租户与跨集群场景下的心智负担,并用"默认 tenant + 默认 namespace + 默认类型"的灵活命名规则让日常使用更加简洁。仓库源码表明,这些变更并非简单替换字符串,而是内建在 TopicName 的解析与归一化逻辑之中:新旧格式由段数自动识别、cluster段缺失即视为 V2、旧格式 Topic 兼容访问。理解这套规则,无论迁移存量集群还是编写新客户端代码,都能少踩"名称不合法"的坑。
- 消息队列
- 后端
- 流处理
【免费下载链接】pulsar
Apache Pulsar - distributed pub-sub messaging system
相关推荐
Apache Pulsar 2.0 版本关键变更解析:Tenant 命名体系与 Topic 名称重构
Apache Pulsar 2.0 版本关键变更解析:Tenant 命名体系与 Topic 名称重构 Pulsar 2.0 是 Apache Pulsar 历史
消息队列后端流处理Apache Pulsar 2.0 升级指南:Tenant 命名体系、Topic 名称简化与 Pulsar Functions 新特性
Apache Pulsar 2.0 升级指南:Tenant 命名体系、Topic 名称简化与 Pulsar Functions 新特性 本篇技术指南以 Puls
消息队列后端流处理Apache Pulsar 2.0 版本指南:Pulsar Functions 新特性与 Topic 命名体系变革
Apache Pulsar 2.0 版本指南:Pulsar Functions 新特性与 Topic 命名体系变革 Apache Pulsar 2.0 是 Pu
消息队列后端流处理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考