
COSCon‘25 的议程一公布同场的 Pulsar Developer Day 时间表也跟着出来了。挂在公告栏上的一瞬间我朋友圈里的消息中间件圈子就炸了一轮。作为一个从 Kafka 时代一路用到 Pulsar 的分布式系统老兵我看到这份议程的第一个感觉是这届的内容密度明显比前几届要实。Apache Pulsar 在国内的关注度这些年起起伏伏但凡是真正在业务里扛过峰值流量的人看到它“计算与存储分离”的架构思路以及多租户、分层存储这些原生能力基本都会觉得“这才是云原生时代该有的消息队列”。这篇东西我想把两件事讲透一是 Pulsar 凭什么在 Kafka 的腹地杀出一条路二是这次开发者日的议程里头哪些内容真正值得你请一天假去现场听。围绕 Pulsar、消息中间件、COSCon 这几个关键词下面我会从架构原理、议程拆解、上手实操、踩坑实录四个层面展开。不管你是架构师、后端开发还是刚入行的运维都能从这里找到对你有用的东西。尤其是那些已经在生产环境里跑着 Kafka、正纠结要不要迁 Pulsar 的团队这篇文章可以当一份选型参考来用。1. 消息中间件到底在解决什么问题1.1 从一次线上故障说起消息队列的价值不是“快”聊 Pulsar 之前先想清楚消息中间件存在的意义。我经历过一次很典型的故障一个订单服务直接 HTTP 调用库存服务平常 TP99 也就是 50 毫秒结果大促流量一上来下游数据库连接池先被打满紧接着上游线程池排队雪球一滚整个订单链路全部超时。这场景你换成食堂就很好理解。高峰期所有人直接冲到窗口点餐窗口后面的厨师根本忙不过来后厨越积越多前面的人越挤越乱。消息队列就是那个叫号取餐的机制你先把单子递进去系统收了订单立刻告诉你“已受理”后厨慢慢做做完广播叫号你来取就行。所以消息中间件的核心价值从来不是为了把单次消息发送时间压到极致而是解决三个问题异步化削峰、模块解耦、流量缓冲。Pulsar 也好Kafka 也好本质上都是在为这三个目标提供更稳的底座。1.2 主流中间件的差异Kafka 是标杆但不是终点现在市面上主流的三款消息中间件Kafka、RocketMQ、Pulsar各自的老家和发展路线差别很大。Kafka 是数据管道和流处理的事实标准吞吐高、生态庞大Flink、Spark 全是它的铁哥们。但它的经典架构是存储与计算不彻底分离Broker 既做服务又管数据扩缩容的成本并不低。近两年的版本引入了 KRaft不再依赖 ZooKeeper但整体设计逻辑还是“以分区日志为中心”。RocketMQ 是阿里系产品事务消息和延迟消息是它的招牌电商和金融场景里验证很充分。它的部署模型和运维体系也相对成熟在中文社区里文档和案例非常丰富。Pulsar 则是后来者里最激进的那个。它在 Yahoo 内部孵化开源后进入 Apache 基金会并成为顶级项目。它的设计目标一开始就是云原生想解决的恰恰是 Kafka 在弹性扩容、多租户隔离、跨地域复制这些场景下的痛点。三者没有绝对的好坏按场景选。但如果你奔着“云原生、多租户、长期留存”去Pulsar 的架构上限确实更高。1.3 Pulsar 的独特定位一套系统队列和流通吃Pulsar 最打动我的一点是它从来不逼你在“队列”和“流”之间二选一。Kafka 天生是流做队列也能做但消费组模型在队列场景下用起来总有点别扭。Pulsar 直接提供了四种订阅类型独占订阅、共享订阅、故障转移订阅、Key 共享订阅。独占订阅就是标准的竞争消费一条消息只给一个消费者共享订阅则是多消费者分摊消息典型的队列模式故障转移让一个消费者主处理、其余备胎Key 共享订阅则保证相同 Key 的消息永远落在同一个消费者上既保证了局部顺序又能水平扩展。这一个能力就让团队不用同时维护一套 Kafka 和一套 RabbitMQ 了。2. Pulsar 架构创新的硬核拆解2.1 计算与存储分离为什么我说它是本质区别Kafka 的经典模式里Broker 既处理客户端请求又在本机磁盘上存日志。这种设计简单直接但有个隐藏问题存储和服务耦合扩容就困难。你想给某个分区加容量往往得迁移整个分区的数据Broker 故障恢复时要么等数据重新复制要么忍受较长的不可用窗口。Pulsar 把这两层彻底拆开了。Broker 是无状态的接入层只负责处理生产者消费者的连接、路由和协议解析真正的数据全部交给底层的 Apache BookKeeper 集群去存储。这就好比餐厅里服务员和后厨的分工客流再多只需要加服务员不需要扩建厨房后厨要扩展也只是加炉灶不用管前台怎么排班。这个拆法带来的用户体验非常直观。Broker 可以像普通无状态服务一样快速扩缩容你甚至可以一分钟内把一个 Broker 从集群里摘掉或加回来。存储层 BookKeeper 扩容时系统会自动做数据重平衡整个过程对业务方透明。这对于那些消息流量忽高忽低、又不想常年为峰值预留机器的团队来说价值是实打实的。2.2 分段存储与 BookKeeper把“追加写”做到了极致很多人第一次听说 Pulsar 的存储模型会有点懵其实核心就一句话Topic 的数据不再是一个持续增长的大文件而是切成了一段一段的 Segment每一段在 BookKeeper 里称为一个 Ledger。为什么要分段因为不可变。Ledger 一旦写好内容就不再修改只能追加。这给系统带来了两个巨大的好处第一底层可以优雅地做多副本复制和故障恢复某个副本坏了从其他副本把整段数据补回来就行第二老的 Segment 达到一定大小或时间阈值后可以整体“退役”系统只需要记住这段数据的元信息内容可以放到便宜的地方去。这套机制的写入路径是这样的生产者发送消息Broker 将消息追加到当前活动的 LedgerBookKeeper 的多个 Bookie 节点同时写入这份数据的多个副本多数派确认返回后Broker 再向生产者确认。生产环境我们一般建议把副本数至少配到 3 个确认 Quorum 配到多数派这样单节点故障不影响写入也不丢数据。我当年从 Kafka 迁移到 Pulsar花了整整一个下午去理解 Ledger 和 Segment 的关系。理解之后再看消费游标Cursor你会豁然开朗Pulsar 的消费位置本身也是存在 BookKeeper 里的元数据相当于整个集群的状态都是分布式的没有单点。2.3 分层存储与多租户无限留存不是梦传统消息队列最让人头疼的一个问题是存储成本。Kafka 的日志默认按时间删除因为磁盘就那点大。你想保留三个月数据做回溯分析先看看硬盘预算。Pulsar 的分层存储直接把答案改变了老 Segment 可以卸载到对象存储比如 AWS S3、阿里云 OSS、MinIO 这类服务上。这意味着什么消息可以设定永久留存本地 BookKeeper 只保留最近几天的热数据更早的全在对象存储里躺着。消费老数据的时候系统会自动从对象存储把数据拉回来。这套机制让我想起“冷热分离”这个词在数据库领域的老用法但 Pulsar 是把这个概念内建到了消息系统里不需要你自己写脚本去搬运。多租户则是 Pulsar 另外一个让我觉得“早该如此”的设计。它用租户、命名空间、主题三级结构来组织资源租户之间可以做权限隔离、配额管控。打个比方一个公司有多个项目组大家共用同一套 Pulsar 集群但每个项目组只能看到自己的命名空间互不干扰。这就省掉了“每个部门单独搭一套消息集群”的巨大浪费。3. 这次 Pulsar Developer Day 议程看什么3.1 议题方向拆解从内核原理到业务落地按照已公开的议程框架这次开发者日的内容大致分布在五个方向内核与架构、云原生与运维、业务落地案例、生态扩展、性能调优。这不是我第一次参加 Pulsar 相关的技术活动但这次的覆盖面明显更偏向“生产可落地”。内核方向通常会深入 Broker 请求处理链路、BookKeeper 写放大与 IO 模型这类硬核话题适合做平台研发的同学云原生方向基本绕不开 Kubernetes Operator 部署、多集群容灾这是很多团队从测试环境走向生产环境时最需要参考的部分业务落地案例则是各个公司分享自己为什么从 Kafka 迁到 Pulsar、迁过去之后踩了哪些坑。这类分享里最值钱的是那些不会写进官方文档的“事故复盘”。如果你让我只建议一个方向我会说业务案例和内核主题都别错过。前者帮你验证选型判断后者帮你建立排障时的全局观。3.2 最值得蹲守的具体内容我自己最期待的是两个方向的session。一个是关于分层存储落地的实践分享因为这块概念宣传多、真实生产数据少我特别想看看别人在对象存储拉取延迟、Offload 策略调优上是怎么做的。另一个是消息轨迹或全链路追踪相关的议题分布式环境下消息丢没丢、延迟在哪一直是排查的难点能有人把方案讲透就很值。另外议程里如果看到“性能压测对比”或“Kafka 迁移”这类字眼建议直接锁定。迁移类议题往往带着血泪史消费组怎么重建、事务消息怎么过渡、双跑期间如何核对数据这些细节在官方迁移文档里根本找不到。现场问答环节千万别提前走。技术大会里最精彩的内容永远不是在台上念 PPT 的时候而是讲完后被追问“你们当时为什么不用 XX 方案”的那个瞬间。3.3 同场活动的隐藏价值社区是活的COSCon 本身是开源社主办的老牌开源大会Pulsar Developer Day 作为同场活动最大的优势就是组织方和参与者里有一大批 Apache Pulsar 的核心维护者和 Committer。这种场合下你很容易找到能直接给你答疑的人。对想贡献开源的同学来说这种活动是最好的入场券。你可以在现场跟维护者聊你在源码里看到的不理解的地方混个脸熟之后提 PR 被 review 的效率都会不一样。对使用方来说同样有价值你生产环境遇到一个 bug直接跟维护者反馈比在 GitHub 上发 issue 等回复要快得多。我带了个笔记本去上面列了十几个生产环境里积累的疑问包括 Ledger 滚动参数调优、消费者 Ack 超时导致的重投问题、Bookie Journal 的 IO 隔离这些问题在技术群里问没人答得清但在开发者日这种场合我通常能要到靠谱的答案甚至能要到维护者的联系方式。4. 从零开始上手 Pulsar单机到生产的实操路径4.1 十分钟在本地跑起单机 Pulsar如果你从来没碰过 Pulsar最快的上手方式是用官方二进制包跑 Standalone 模式。去官网下载对应版本的 tar.gz 包解压后直接执行bin/pulsar standalone这个命令会把 Broker、BookKeeper、本地元数据服务一次性拉起来默认监听两个端口6650 是客户端二进制协议端口8080 是 HTTP 管理端口。启动完成后在浏览器打开http://localhost:8080就能看到 Admin 相关的 API 服务。验证消息收发也很简单打开另一个终端bin/pulsar-client produce -m hello pulsar persistent://public/default/demo-topic bin/pulsar-client consume -s demo-subscription persistent://public/default/demo-topicTopic 的完整名称persistent://public/default/demo-topic是有讲究的三段式分别是持久化类型、租户、命名空间、主题名。这套命名规则比 Kafka 的裸 topic 名更规范从一开始就逼着你按照多租户的方式思考。Standalone 模式只适合本地学习和跑 Demo这一点怎么强调都不为过。我有次图省事想拿 Standalone 模式做线上小流量验证结果消息稍微多起来就各种连接超时。后来老老实实搭了三个 Bookie 的集群世界才清净。4.2 最小可用的生产者与消费者代码Java 客户端是 Pulsar 支持最完善的官方客户端之一。下面这段代码是你能写出的最小生产消费对import org.apache.pulsar.client.api.*; PulsarClient client PulsarClient.builder() .serviceUrl(pulsar://localhost:6650) .build(); ProducerString producer client.newProducer(Schema.STRING) .topic(persistent://public/default/demo-topic) .create(); producer.send(hello pulsar); ConsumerString consumer client.newConsumer(Schema.STRING) .topic(persistent://public/default/demo-topic) .subscriptionName(demo-sub) .subscriptionType(SubscriptionType.Shared) .subscribe(); MessageString msg consumer.receive(); System.out.println(msg.getValue()); consumer.acknowledge(msg); client.close();这段代码有两个细节值得注意。第一subscriptionType我特意选了Shared这样才能同时启动多个消费者分摊消息如果你省略这行默认是Exclusive同一订阅名下只允许一个消费者存在多起一个就会报错。第二consumer.receive()是阻塞调用收到消息后一定要acknowledge否则这条消息会被认为是未确认后续在 Ack 超时后重新投递。真实业务里消费者通常不会用这种同步阻塞方式而是配合线程池或 Pulsar 的MessageListener异步回调。但从这段最小代码开始理解收发模型比直接套框架要扎实得多。4.3 从 Demo 到生产环境必须跨过的几道坎单机 Standalone 玩明白了离生产还差着十万八千里。我总结了几道必须跨过的坎每一道当年都让我交过学费。第一集群规模别拍脑袋。一个最小可用生产集群至少需要 3 个 BookKeeper 节点、3 个元数据服务节点通常用 ZooKeeper、2 个以上的 Broker。BookKeeper 节点建议用 SSD 做 Journal 盘Journal 单独挂盘不要跟系统盘混在一起。第二认证和权限是必修课。Pulsar 支持 Token 认证、OAuth2、TLS 双向认证等生产环境至少要把认证开起来租户与命名空间级别做 ACL。裸奔的 Pulsar 集群跟裸奔的 Redis 一样是在给黑客递刀。第三资源和策略预设好。创建命名空间时就把 Retention留存策略、Backlog Quota积压配额和消息 TTL 配明白不要等上线后再补。文档里写得清楚但大多数人都是踩过“消息无限留存导致磁盘暴涨”的坑之后才回头补课。第四监控体系要同步建设。Pulsar 的指标比 Kafka 丰富得多Broker、Bookie、Topic 三个层面都有大量指标。至少要把积压Backlog、消费 Lag、存储用量、Bookie Journal 写延迟这几个核心指标接进你的监控系统。5. 我在 Pulsar 上踩过的坑生产环境排查实录5.1 消费积压失控Shared 订阅的隐身陷阱我第一次在 Pulsar 上做业务时遇到的最头疼的问题就是消费堆积。现象很典型某个 Topic 的消费积压从几百条一路涨到几十万条报警器响个不停。起初我以为是消费者处理能力不够加了两台机器结果积压还在涨。后来用管理命令一查bin/pulsar-admin topics stats persistent://public/default/demo-topic输出里的backlog字段清楚显示积压而重点在subscription部分。我仔细观察才发现问题出在消息确认上消费者代码里处理了消息但因为异常路径上没有执行acknowledge消息一直被当成未确认Ack 超时后又重新投递形成了无限循环。这个坑总结下来就是一句话消息处理的失败重试一定要设计好终态。要么进入死信队列DLQ要么在重试一定次数后丢弃并记录日志绝不能让消息无限重投。另外处理消息的业务逻辑要做到幂等因为 Pulsar 在极端情况下确实可能发生重复投递这不是 bug是分布式系统的常态。另一个跟积压相关的点是订阅模型的选择。如果你用的是默认的Shared订阅消息会平均分发给所有消费者但每个消费者的处理速度不同整体积压就会受最慢的那个拖累。如果业务里消息有明确的 Key 顺序要求建议优先考虑Key_Shared订阅它保证相同 Key 的消息只发给同一个消费者既能保序又不会因为一个消费者卡住导致全局积压。5.2 BookKeeper 磁盘与 IO看起来没事其实已经要命BookKeeper 是 Pulsar 的存储底座它出问题整个 Pulsar 都别想好过。我遇到过一个特别隐蔽的故障集群运行平稳消息延迟却整体抬高了 30%。查了半天发现是某台 Bookie 的 Journal 盘和 Ledger 数据盘混用写放大的顺序写被随机读干扰了。BookKeeper 的数据写入路径是严格顺序写 Journal然后异步刷入 Ledger 存储。Journal 相当于数据库的 WAL它的延迟直接决定消息写入的延迟。生产环境里Journal 必须用独立的 SSD 或 NVMe 盘并且要确保fsync策略合理。默认配置在大多数场景下可用如果你追求极致性能需要评估journalSyncData、journalMaxGroupWaitMSec等参数它们控制的是“攒一批再刷盘”的批量策略。排查这类问题我的经验是先看指标bin/pulsar-admin broker-stats monitoring-metrics | grep journal重点关注 Bookie 的 Journal 写入延迟和 Ledger 存储的读取延迟。如果 Journal 延迟持续走高第一件事确认盘是不是独享第二件事看是不是有消费者在大量回放老数据占用了 IO。分层存储在帮你省成本的同时也要注意回放历史数据会触发对象存储的读取那部分延迟完全是另一个量级的。5.3 常见问题速查表下面这个表格是我在实际运维中沉淀下来的速查表遇到问题可以直接参照。症状可能原因优先排查动作生产者发送超时Broker 负载过高或 BookKeeper 写确认慢看 Broker 的请求队列指标看 Bookie Journal 写延迟消费积压不断增长消费者处理能力不足或消息未正确 Ackpulsar-admin topics stats查看各订阅 backlog检查异常重投逻辑消费端偶发重复消息Ack 超时后消息重投确认消费者的ackTimeout配置确保业务处理幂等单 Topic 吞吐上不去分区数不足或单个 Broker 成为瓶颈增加分区数检查 Producer 的maxPendingMessages参数Bookie 磁盘占用暴涨Retention 策略未设置或 Offload 未配置检查命名空间 retention 与 tiered storage 配置客户端频繁重连认证配置错误或网络不稳定查看 Broker 日志中的连接断开原因验证 TLS/Token 配置消费者组无法加入订阅类型为 Exclusive 且已有消费者在线改为 Shared 或 Key_Shared或等待原消费者离线这表格看着简单每一条背后都是我熬过的夜。尤其是“重复消息”和“积压”这两条它们往往同时出现且根因都在业务代码而不是消息中间件本身。所以排查时一定要有耐心先把客户端日志和指标拉齐再动集群配置。6. 选型建议与参会前的准备6.1 什么业务场景真正适合上 Pulsar先说结论不是所有人都需要 Pulsar但以下几类团队我强烈建议你认真评估。第一类是跑在 Kubernetes 上的团队。Pulsar 天然为云环境设计计算层无状态、存储层独立扩展配合官方或社区维护的 Operator在 K8s 上部署和扩容的体验比传统消息中间件好一个档次。如果你已经在云原生技术上投入了资源引入 Pulsar 的学习成本会比想象中低。第二类是多团队共用基础设施的公司。Pulsar 的多租户模型允许你在一个集群里服务多个业务方每个租户有独立的配额和权限运维团队从“给每个部门搭一套集群”变成“维护一套集群给所有人”管理和成本上都划算得多。第三类是有长期消息留存需求的团队。比如你需要保留全量事件数据做离线分析或者业务要求消息可回放周期长达数月甚至永久分层存储的存在让这件事的成本变得可控。换成 Kafka你得一直买大容量磁盘还得天天操心删除策略。第四类是跨地域多机房部署的业务。Pulsar 内置的跨地域复制能力让消息可以在多个集群之间同步容灾切换的复杂度远低于自研双活。6.2 什么情况下我劝你等等反过来说也有几类情况我建议先别急着上 Pulsar。团队没有专人负责消息中间件的深度运维只靠几个后端开发兼职维护那 Kafka 或 RocketMQ 的生态成熟度、社区中文资料量和招聘市场上的熟练度都是更稳妥的选择。业务模式极其稳定消息量几年都见不到大幅增长团队也没有扩展计划那确实没有必要为架构的先进性买单。工具再好解决不了真实问题就只是成本。还有一个现实因素Pulsar 的国内社区布道资源确实没有 Kafka 那么铺天盖地招一个熟练的 Pulsar 运维工程师比招 Kafka 的要难。这个账要算进去别只看技术对比的 PPT。6.3 参会前建议带上这张清单确定要去现场的话我给你一份自己的经验清单第一带上你最近半年遇到的故障清单不要是“连接超时”这种流水账而是像“某次 Bookie 数据盘损坏后恢复过慢”“某个租户的 Topic 被其他租户的高吞吐影响了”这样有细节的问题。这类具体问题在现场跟维护者聊收获远超你预期。第二提前做好功课至少把 Pulsar 官方文档里关于架构和运维的部分读一遍。不要在现场问文档里就有答案的问题浪费双方时间问出来还挺尴尬的。第三同场活动通常不需要单独购票但 COSCon 的主会报名要提前完成别到了门口才发现没注册。议程时间和场地信息以官方渠道为准出发前一天再确认一次。第四准备好加联系方式的话术。开发者日这类活动最大的资产是人。你不需要认识所有人认识两三个核心维护者或者三五个同行公司的平台同学就值回票价了。7. 我对 Pulsar 现状的一点个人体会这些年我在不同的公司先后维护过 Kafka、RabbitMQ、RocketMQ最后在 Pulsar 上深耕。很多人问我是不是“Pulsar 吹”我的回答是工具是用来解决问题的不是用来信仰的。Pulsar 确实有很多让我眼前一亮的设计但它的复杂度和学习曲线也比传统中间件高这是事实。我个人在实际使用中最受益的一点是它把“分布式消息系统”的复杂度模块化得很清晰。Broker 搞不定就看 BookKeeperBookKeeper 搞不定就看元数据服务每一层的问题边界都很清楚。相比之下早期 Kafka 出了问题你很难判断是协调器、日志存储还是副本同步哪个环节在作妖。这种排查体验的差异只有真正在生产环境扛过故障的人才会懂。最后再分享一个实用的小技巧去现场之前把你要讨论的 Topic 在pulsar-admin里的stats输出截图存下来。遇到维护者直接拿截图聊参数比空口白话清楚得多。我记得有次我就是拿着一张积压事故的监控截图跟一个 Committer 聊了半小时把managedLedgerNewEntriesCheckDelayInMillis这个参数调优的思路彻底搞明白了。这种收获不是刷几天技术论坛能拿到的。这次 COSCon‘25 的 Pulsar Developer Day虽然主题列表摆在那里但真正的价值藏在每个 Session 结束后的交流里。如果你恰好也在评估消息中间件或者已经在 Pulsar 的路上建议你到现场亲身体验一下。带上问题带上好奇心剩下的交给现场。