COSCon'25和Pulsar Developer Day 2025放在同一场地的那天早上,我站在签到处翻着日程表,心里第一反应是:消息队列(MQ)这个被喊了十几年"老技术"的领域,到底还有多少人愿意专门为它跑一趟开发者日?结果开场半小时我就发现自己想岔了。主会场走廊过道全是人,白板上的讨论稿写了又擦、擦了又写,从上午到散场,围着"Pulsar存算分离""Broker无状态扩容""多租户隔离"这些问题聊的人就没断过。
"Make MQ Great Again"这个标语挂在会场最显眼的位置。我第一眼看到的时候觉得好笑,但认真逛了一圈之后理解了——在技术语境里这四个字说的不是口号,而是一个真实存在的行业状态:消息中间件正在经历一轮实打实的架构重构。这篇文章就把这届活动上我听到、看到、并且自己验证过的东西整理出来,包括Pulsar为什么能在这轮讨论里站到C位、它的核心机制到底解决了什么问题,以及我顺手在现场走读的一个物联网端侧场景——STM32环境监测链路怎么跟消息中间件接起来。适合做后端架构选型、搞物联网接入、或者纯粹对MQ技术演进好奇的读者参考。
1. 为什么"重振MQ"成为这届COSCon'25绕不开的话题
先说一个很多人不愿承认的事实:消息中间件这个领域,过去十年里其实没有发生过真正意义上的架构级创新。大家提到MQ,脑子里浮现的无非是几个固定答案——Kafka吞日志很强,RabbitMQ做业务解耦顺手,RocketMQ在金融场景里有口碑。这些结论本身没错,但它们的底层模型都是围绕"分区""队列""消费组"这三个概念转,转来转去,运维上的老问题一个都没少。
1.1 消息队列的"老问题清单"
我在会场上随手记下了几个高频吐槽点,基本就是当前主流选型的真实痛点:
- 分区扩容要迁移数据。Kafka的分区一旦定了,想加分区、换Broker、挪副本,都要触发数据重平衡,集群越大,重平衡越痛苦。
- Broker和存储绑死。传统模型里每个Broker节点自己扛磁盘,想扩容量得加节点,加了节点又得做数据再分布,存储和计算没法各自伸缩。
- 租户隔离靠"拆集群"。很多团队为了隔离不同业务,直接物理拆出好几套集群,运维成本直接翻倍。
- 消费模型单一。队列模型和流模型的边界很模糊,一个Topic想既给流处理用、又给业务队列用,配置起来经常别扭。
这些问题单独拎出来任何一个,大家都能忍。但攒在一起,就变成了一个很尴尬的局面:中间件成了分布式系统里最不好伺候的那一块。而这正是Pulsar这类"云原生架构"的中间件能在这届活动现场被反复讨论的根本原因。
1.2 从现场观众构成看MQ需求的三个方向
我在现场观察到一个很有意思的现象:来听Pulsar议题的人,明显分成了三个群体,需求完全不一样。
第一个群体是互联网公司的后端架构师,他们关心的是"我能不能把Kafka迁到Pulsar,省掉分区重平衡的运维噩梦";第二个群体是做SaaS和B端系统的团队,他们关心的是"一个集群能不能同时服务几十个客户,并且互相不干扰";第三个群体最让我意外——不少做物联网和硬件接入的人。他们的问题集中在"设备上报的数据量不大但连接数很多,消息中间件能不能扛得住"。
这三个群体对应的是MQ选型的三个真实驱动力:运维复杂度、多租户隔离、海量连接。而这三点恰恰是Pulsar在架构设计上优先解决的问题。所以与其说Pulsar是来"取代谁"的,不如说它是来回答一个更根本的问题:消息中间件能不能真正做到按需伸缩、自带隔离、原生支持多种接入协议。这届活动上所有的技术分享,基本都围绕这个核心在场内外展开。
2. Pulsar在开发者日上被反复论证的四个硬核点
接下来这部分是我认为整场活动信息密度最高的地方。Pulsar的技术分享不少见,但开发者日的优势在于,讲师会直接放生产环境的实测数据,而不是只讲PPT。我挑四个讨论最热烈的机制来说,每一个都在现场被追问到了底层。
2.1 存算分离:把"仓库"和"调度中心"分开
Pulsar架构里最核心、也最容易被误解的就是存算分离。用大白话解释:传统Kafka是"运输队和仓库绑在一起"——每个Broker既管接收数据,又管把数据写在本地磁盘,车队要扩大,必须先盖仓库;而Pulsar把这两件事拆开了,Broker只负责接收请求、维护元数据、分发消息,数据本身交给另一层叫BookKeeper的存储节点去持久化。
这意味着什么呢?第一,Broker可以做到真正的无状态,想加就加,想减就减,不需要迁移任何数据。第二,存储层扩容极其简单——往BookKeeper里加Bookie节点就行,新数据会自然分布到新节点上,旧数据不需要大规模重分布。第三,资源可以独立调配:计算压力大就加Broker,存储不够就加Bookie,互不拖累。
当时有个参会者问了一个很尖锐的问题:存算分离之后,一条消息从发给Broker到真正落盘,路径变长了,延迟是不是会变差?讲师直接放了一组数据:Pulsar的端到端延迟(P99)在生产环境可以稳定维持在几十毫秒级别,对于大部分业务消息场景完全是可接受的,而且由于BookKeeper是追加写的日志模型,顺序写盘效率反而很高。也就是说,你用架构上的"多一跳",换来了巨大的运维灵活性,这笔账是划算的。
2.2 多租户隔离与统一配额管理
第二个被反复讨论的是Pulsar的多租户模型。它把资源分成了三级:租户(Tenant)、命名空间(Namespace)、主题(Topic)。租户对应一个业务线或一个客户,命名空间对应一个项目或环境,主题就是具体的数据通道。
这套模型的实际价值在于:一个集群可以同时服务多个业务线,互不干扰,还能做到真正意义上的配额隔离。比如你给A租户配了100GB存储配额和每秒10万条的消息速率限制,给B租户配了10GB和每秒1万条,这两个租户的Topic可以物理上落在同一批Bookie上,但谁也别想抢谁的资源。
现场有做SaaS的工程师分享了一个很典型的例子:他们一个集群收了三十多个客户的流量,每个客户一个租户,通过命名空间区分生产环境和测试环境。遇到某个客户突发流量,直接给对应租户调配额就行,其他客户完全无感。这个能力在传统MQ里几乎是不可想象的——以前要么拆集群,要么被"噪音邻居"问题折磨。多租户这个特性,对任何需要面向多业务方提供消息能力的团队来说,都是实打实的降本手段。
2.3 四种订阅模型与消费模式的组合
Pulsar在消费模型上的设计也是现场讨论的热点。它把"订阅"和"消费"分开理解,四种订阅类型覆盖了几乎所有消息场景:
- 独占订阅(Exclusive):一个Topic同一时刻只允许一个消费者,适合严格有序处理的场景。
- 共享订阅(Shared):多个消费者轮询拉取消息,适合吞吐优先、不需要严格顺序的任务队列。
- 键共享订阅(Key_Shared):按消息Key把消息路由到固定的消费者,同一Key的消息有序,不同Key的可并行,这是非常实用的折中方案。
- 故障转移订阅(Failover):多个消费者绑定一个Topic,主消费者挂了自动切到备用的,适合需要高可用但不想牺牲顺序的场合。
我当时就想,要是早几年有这个模型,很多团队就不用为了"既要顺序又要并行"这种需求去自研一层路由了。这四种订阅类型和Pulsar的多租户能力结合起来,基本可以覆盖从流处理到业务解耦的绝大多数场景。
2.4 跨地域复制与容灾的实操意义
活动上还有一个话题让我印象很深:跨地域复制。Pulsar原生支持多个集群之间的异步复制,消息在本地集群写入后,会异步同步到远端集群。这跟我们常见的"主备切换"不同,它是双向的、多活的结构,每个集群都是独立的生产和消费入口,数据在多个地域之间互相复制。
对一个有容灾要求的系统来说,这个能力意味着:你的消息中间件不需要再单独搭一套复杂的数据同步工具,配置几行就能建立跨地域的数据通道。现场有个做金融支付场景的工程师分享,他们用Pulsar的双集群复制做机房级容灾,数据损失窗口控制在秒级,切换时几乎无感知。当然,跨地域复制有个前提是网络质量要好,这个我们在国内的云环境下基本都是满足的。
3. 当MQ真正下沉到硬件:一个STM32环境监测链路的现场走读
说实话,我的关注点本来只在服务端架构上,但这次活动有个环节很特别——现场摆了一个用STM32做环境监测的端到端demo,从传感器采集到消息中间件再到云端展示全链路打通。当时围了一圈人,我挤进去看完之后发现,这其实就是把消息队列用在物联网场景最好的教学案例。
3.1 从MQ-2到MQ:一个有趣的名字插曲
先说个现场的乌龙。有人看到demo板上的气体传感器写着"MQ-2",第一反应是"这怎么还跟消息队列同名了",还专门回头去确认自己没走错会场。其实这里的MQ是英文"气体敏感材料"相关命名的历史遗留叫法,跟消息队列Message Queue的缩写完全就是一个巧合。但这正好成了一个很生动的隐喻:硬件端的传感器在采集数据,软件端的消息队列在搬运数据,两个"MQ"在一条链路上碰了面。这届活动的标题叫"Make MQ Great Again",某种程度上也像是给这两个"MQ"一起喊的话。
3.2 端侧采集的完整链路
我把那个demo的硬件链路拆开整理了一下,完全复刻成本不高,物料都很便宜,适合拿来练手。主要模块包括:
- STM32F103C8T6主控板,或者带WiFi的ESP32也可以,看你想不想让设备直接联网。
- DHT11温湿度传感器,用的单总线协议,读取时序要卡准,数据脚接普通GPIO。
- BH1750光照传感器,走I2C总线,分辨率可以到1勒克斯,量程覆盖1到65535。
- MQ-2气体传感器,输出是模拟量,用ADC采样,上电后需要预热一会儿再读数值。
- OLED屏,通常是SSD1306驱动,I2C接口,用来本地显示读数。
采集逻辑不复杂,我整理成大概这样的流程:
while (1) { 定时1秒: 读DHT11 -> 温度 + 湿度 读BH1750 -> 光照强度 读MQ-2(ADC多次采样取均值) -> 气体浓度标定值 OLED刷新显示 MQTT发布:{"temp":26.5,"humidity":48.0,"light":320,"gas":0.21} delay(1000); }实际做的时候有几个小坑:DHT11的读到一半总线就被拉低会卡死,最好加超时退出;BH1750有几种测量模式,连续高分辨率模式适合做监测;MQ-2的模拟值受供电电压影响,建议用稳定3.3V或5V供电,并且记录基线值做相对比较,而不是直接拿绝对值当标准浓度。
3.3 为什么IoT数据值得走消息中间件而非HTTP直连
这个demo真正有意思的地方,不是采集本身,而是数据传输环节的设计逻辑。很多做硬件原型的人第一反应是"设备直接HTTP POST到服务器",但当设备量上来以后,HTTP直连的坑会越来越明显。
设备端到服务器之间加一层消息中间件,解决的是三个很实际的痛:第一,连接不是短命的一次性请求,而是长连接,设备状态可以被服务端实时感知;第二,数据先落到Topic里,消费端按自己的节奏拉取,服务器临时抖动也不会丢数据;第三,多个来源的数据可以在同一个集群里统一处理,比如环境监测数据、设备心跳、告警事件全部进入Pulsar,再按租户和命名空间分类,后期无论是写库还是触发告警,都有清晰的通道。
现场这个demo用的是MQTT协议从传感器接入,然后通过Pulsar的MQTT协议适配能力直接进入Topic,后续有订阅者负责把数据写入时序数据库做展示。这套链路的优雅之处在于:你完全不需要为物联网场景单独建一套后端,消息中间件天然就把"设备接入"和"业务处理"解耦了。
4. 围观之后要想清楚的三件事:避坑经验与选型复盘
参加完活动,最值钱的其实不是"Pulsar好棒"这种结论,而是搞清楚"它到底好在哪,以及哪些场景不应该用"。我在现场和一些已经落地Pulsar的工程师聊完,加上回去后自己做了几天压测和部署测试,整理出三条最容易犯的认知偏差。
4.1 误区一:Pulsar只能跑在K8s上
活动上有人一听到云原生就默认必须上K8s,这个想法其实是把云原生和容器编排绑定死了。Pulsar确实在K8s里有官方Operator,部署很丝滑,但对于中小团队来说,用Docker Compose在几台裸机上跑一个最小集群也完全可行,甚至搭配二进制包直接部署都能跑得很稳。
我实测下来,单机部署Pulsar做功能验证非常快,跑起来只需要一个ZooKeeper(或自带的元数据服务)、一个Broker、一个Bookie。真正要注意的是生产环境的存储规划:BookKeeper的Journal盘和Ledger盘要分开,Journal盘用SSD,Ledger盘可以用机械盘做低成本的大容量存储。这种配置细节比纠结"用不用K8s"重要得多。
提示:最小可用集群跑通之后,再考虑到底要不要K8s。很多团队的生产流量其实还没大到需要弹性扩容,先把JVM内存参数、磁盘规划、监控告警这些基础做好,收益更大。
4.2 误区二:存算分离只是"Kafka加外部存储"
这是在会上被讲师正面纠正过的理解。存算分离不是把Kafka的消息搬到对象存储里就叫分离,关键是两个方向的独立弹性:Broker不持有任何数据,扩容时不需要数据迁移;BookKeeper以追加日志的方式提供高吞吐持久化,数据保留策略、副本策略都由存储层统一管理。
所以你会发现一个很实际的效果:当你需要增加Topic或调整保留时间时,Pulsar的操作是秒级的,你不需要关心数据被存到了哪台机器、磁盘够不够、要不要重平衡。这在Kafka里是好几件事,在Pulsar里是一件事。真正的价值不是"架构上很酷",而是日常运维里省下的那无数个小时。
4.3 误区三:多租户是大型团队才会用到的东西
我一开始也觉得,自己团队就一个业务线,要啥租户隔离。但仔细想一下:开发环境、测试环境、生产环境,是不是就是三个天然隔离的空间?在Pulsar里,把它们放进三个命名空间,甚至分属不同租户,你就能对每个环境设置独立的保留策略、存储配额和权限控制。开发环境产生的垃圾Topic不会污染生产,测试环境的流量再大也卡不到生产数据——这就是多租户的最小落地场景。
4.4 一张选型表与一个冷静的边界
综合这届活动上的讨论,我把几个主流的消息中间件做成一张对照表,方便做选型时直接参考:
| 维度 | RabbitMQ | Apache Kafka | Apache RocketMQ | Apache Pulsar |
|---|---|---|---|---|
| 核心定位 | 企业级消息路由 | 高吞吐流数据管道 | 金融级可靠消息 | 云原生流与队列一体化 |
| 吞吐量级 | 万级 | 百万级 | 十万级 | 百万级 |
| 消息模型 | 队列为主 | 分区+消费组 | Topic+队列 | Topic+订阅 |
| 多租户隔离 | 弱,靠拆实例 | 弱,靠Topic约定 | 中 | 原生三级隔离 |
| 数据保留 | 短,消费即删 | 按磁盘大小保留 | 按时间保留 | 按策略精细化控制 |
| 扩容体验 | 加节点 | 加节点+重平衡 | 加节点+迁移 | 计算/存储独立加 |
| 适合场景 | 异步解耦、任务分发 | 日志、实时数仓 | 事务消息、订单 | 混合负载、IoT多租户接入 |
选型时最关键的一条边界是:流量很小、业务简单、团队运维时间有限的场景,别盲目上Pulsar。它再能打,也需要你理解BookKeeper、懂存储规划、能配置租户策略。如果你的需求就是"几十个微服务之间发个异步消息",RabbitMQ的那点运维成本反而更低。技术选型从来不是选最先进的,而是选最匹配你当前复杂度的。
活动散场时我在门口站了一会儿,几个参会者还在聊Pulsar与Kafka的迁移对比。回想这届COSCon'25和Pulsar Developer Day,给我留下最深印象的不是具体某个功能点,而是大家终于开始认真讨论"消息中间件应该长成什么样子"这个问题本身。从现场那个把STM32传感器接入消息队列的demo,到多租户隔离在生产环境的真实分享,其实都在说明一件事:MQ这个"老家伙"并没有过时,它只是在换一种更符合云时代和物联网时代需求的方式存在。如果你正在纠结消息中间件选型,我的建议很简单——先把流量模型算清楚,再把团队能付出的运维精力算清楚,然后带着这两个数字重新回去看一遍这些对比,答案会比你想的明显很多。