☰
Apache Pulsar 2.0 命名体系变革解析:Property 到 Tenant 与 Topic 命名规则演进
2026/9/28 3:05:01 网站建设 项目流程
  • 消息队列
  • 后端
  • 流处理

【免费下载链接】pulsar

Apache Pulsar - distributed pub-sub messaging system

项目地址:https://gitcode.com/gh_mirrors/pulsar28/pulsar
点击查看免费下载

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
tenantpublic
namespacedefault

下表给出利用隐式默认值进行名称"翻译"的示例:

输入的 Topic 名翻译后的完整 Topic 名
my-topicpersistent://public/default/my-topic
my-tenant/my-namespace/my-topicpersistent://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 中。

迁移与实战建议

综合原文档与仓库现状,给出以下实操要点:

  1. 旧集群无需迁移:采用persistent://tenant/cluster/namespace/topic旧格式的存量 Topic 会继续工作,官方无变更计划,可放心升级。
  2. 新代码一律使用新格式:新建 Topic 时推荐写全persistent://<tenant>/<namespace>/<topic>(或non-persistent://...),避免歧义;仅在明确依赖默认值时可使用my-topic这类短名。
  3. 非持久化 Topic 必须写全名:non-persistent://public/default/my-topic,不能使用non-persistent://my-topic简写。
  4. 管理命令使用 tenants:统一使用bin/pulsar-admin tenants create/list/get/update/delete,不要再使用properties系列命令。
  5. 注意名称合法性: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

项目地址:https://gitcode.com/gh_mirrors/pulsar28/pulsar
点击查看免费下载
上一篇:10分钟跑通采购比价引擎:用FastGPT搭建自动比价的实战指南
下一篇:色彩表示系统完全指南:Munsell色彩体系与十六进制编码解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询