简介Apache Pulsar 2.9.1 二进制发行包面向分布式消息中间件开发者、大数据与实时流处理工程师以及需要在云原生环境中搭建高可用消息队列的技术团队。该压缩包约 321.53MB内含部署与运行 Pulsar 所需的二进制文件、客户端库、启动脚本及辅助工具解压后即可按官方文档配置并启动服务。Pulsar 采用发布/订阅模型支持共享、独占与故障转移等多种订阅类型并借助 BookKeeper 实现低延迟持久化存储与消息分层存储配合 ZooKeeper 管理主题分区、集群配置与租约信息保障分布式环境下的一致性与容错能力。其云原生特性可无缝集成 Kubernetes便于在公有云或私有云上水平扩展。Pulsar Functions 还支持在平台内直接处理与转换消息简化轻量级流处理逻辑。目前已有 151 人学习关注适合希望深入掌握分布式消息系统架构与部署实践的中高级开发者参考使用。1. 从一份二进制包说起Pulsar 2.9.1 到底解决了什么如果你正在搭一套云原生架构下的消息中间件大概率绕不开两个选择Kafka 还是 Pulsar。Kafka 生态成熟、资料多但存算一体的架构在弹性扩缩容时总让人头疼——扩容要搬数据缩容怕丢副本。Pulsar 走的是另一条路计算层Broker和存储层BookKeeper分离Broker 无状态存储层可以独立扩缩。这个设计在云原生场景下意味着什么Broker 挂了直接拉起来就行不用等数据恢复存储不够了加 BookKeeper 节点不影响 Broker 层。apache-pulsar-2.9.1-bin.tar.gz 就是这套系统的官方二进制发行包。解压即用不需要从源码编译内置了 Broker、BookKeeper、ZooKeeper用于元数据管理、Proxy、Pulsar Manager 等组件。2.9.1 这个版本属于 Pulsar 2.9.x 系列的稳定维护版支持多租户、分层存储、Pulsar Functions、事务消息等核心特性。它适合谁一是想快速搭一套多租户消息平台的后端团队二是已经在用 Kafka 但被扩缩容问题困扰、想评估替代方案的架构师三是需要消息队列支持地理复制Geo-replication的场景。这份包拿到手之后最直接的用法是单机快速起一套环境验证功能然后再拆开部署到多节点集群。下面从目录结构、配置参数、集群搭建到踩坑排查一步步拆。2. 解压之后先别急着启动目录结构与核心配置拆解2.1 目录布局与各组件的角色解压apache-pulsar-2.9.1-bin.tar.gz之后根目录下有几个关键文件夹先搞清楚谁是谁目录作用bin/所有启动脚本包括pulsar主入口、pulsar-daemon后台启动、bookkeeper、zookeeper等conf/配置文件pulsar.conf、bookkeeper.conf、zookeeper.conf、proxy.conf都在这里lib/所有依赖 jar 包Pulsar 的插件机制也依赖这里的 classpathlogs/运行日志排查问题第一站data/默认数据目录ZooKeeper 和 BookKeeper 的数据落在这里instances/多实例部署时的实例目录单机模式下用不到Pulsar 的架构里ZooKeeper 管元数据租户、命名空间、Topic 归属BookKeeper 管消息存储Ledger 写入和读取Broker 管连接和路由。三者可以部署在同一台机器上单机模式也可以拆开集群模式。2.9.1 的二进制包默认配置就是单机三合一适合先跑通再拆。2.2 单机模式启动三条命令与背后的参数单机模式启动最简单但要知道每条命令背后在干什么# 1. 启动单机版 Pulsar前台运行CtrlC 停止 bin/pulsar standalone # 2. 如果想后台运行用 daemon 模式 bin/pulsar-daemon start standalone # 3. 停止后台运行的实例 bin/pulsar-daemon stop standalonepulsar standalone这条命令实际上做了几件事先启动一个内嵌的 ZooKeeper 实例监听 2181 端口再启动一个 BookKeeper 实例监听 3181 端口最后启动 Broker监听 6650 用于客户端连接8080 用于 HTTP 管理接口。所有数据默认写在data/standalone/下面。如果你机器上已经有 ZooKeeper 在跑2181 端口会冲突启动直接报Address already in use。这时候要么停掉已有的 ZooKeeper要么改conf/standalone.conf里的zookeeperServers和configurationStoreServers端口。我一般会先lsof -i:2181确认一下端口占用情况。2.3 关键配置项哪些参数必须改哪些可以不动单机验证阶段大部分参数不用动但有几个配置项在往集群迁移时一定会碰到提前理解# conf/broker.conf 中几个核心参数 # Broker 对外暴露的地址集群模式下必须改成实际 IP 或域名 advertisedAddresslocalhost # Broker 监听的端口 brokerServicePort6650 webServicePort8080 # 元数据存储地址单机模式下指向本地 ZooKeeper metadataStoreUrlzk:localhost:2181 # BookKeeper 集群地址 bookkeeperMetadataServiceUrizk:localhost:2181 # 是否允许自动创建 Topic生产环境建议关掉 allowAutoTopicCreationtrue # 消息保留策略默认不删除生产环境必须配 defaultRetentionTimeInMinutes0 defaultRetentionSizeInMB0advertisedAddress这个参数是集群部署时最容易翻车的地方。它决定了 Broker 告诉客户端「你应该连我哪个地址」。如果配成localhost远程客户端拿到这个地址后连不上报Connection refused。集群模式下必须改成每台 Broker 的实际 IP 或可解析的主机名。allowAutoTopicCreation在开发阶段很方便但生产环境建议设为false否则任何拼错的 Topic 名都会自动创建时间一长命名空间里全是垃圾 Topic。常见做法是通过 Pulsar Admin 显式创建 Topic或者用命名空间的autoTopicCreationOverride策略做细粒度控制。defaultRetentionTimeInMinutes和defaultRetentionSizeInMB默认都是 0意思是消息永不删除。单机测试无所谓生产环境不配这个磁盘迟早爆。一般按业务需求设成 100807 天或 4320030 天。3. 从单机到集群ZooKeeper、BookKeeper、Broker 的拆解部署3.1 集群拓扑与部署顺序单机跑通之后下一步是把三个组件拆到不同节点上。典型的最小集群拓扑是3 台 ZooKeeper元数据高可用、3 台 BookKeeper存储高可用、2 台 Broker计算层无状态可随时扩。部署顺序有讲究先起 ZooKeeper再起 BookKeeper最后起 Broker。因为 BookKeeper 启动时要往 ZooKeeper 注册元数据Broker 启动时要同时连 ZooKeeper 和 BookKeeper。# 在每台 ZooKeeper 节点上执行 bin/pulsar-daemon start zookeeper # 在每台 BookKeeper 节点上执行 bin/pulsar-daemon start bookkeeper # 在每台 Broker 节点上执行 bin/pulsar-daemon start broker注意pulsar-daemon和直接pulsar的区别pulsar-daemon会 fork 到后台并把 PID 写到data/目录下方便后续 stop。直接pulsar是前台运行适合调试。3.2 ZooKeeper 配置元数据一致性的根基ZooKeeper 在 Pulsar 里管的是元数据不是消息数据。元数据包括租户列表、命名空间列表、Topic 的归属 Broker、Schema 信息等。这些数据量不大但一致性要求极高。conf/zookeeper.conf里几个关键参数# 集群中每台 ZooKeeper 的编号从 1 开始每台不同 server.1zk1.example.com:2888:3888 server.2zk2.example.com:2888:3888 server.3zk3.example.com:2888:3888 # 数据目录确保磁盘有足够空间 dataDirdata/zookeeper # 客户端连接端口 clientPort2181 # tickTime 是 ZooKeeper 的基本时间单位毫秒 tickTime2000 # initLimit 和 syncLimit 是 tickTime 的倍数 initLimit10 syncLimit5server.N里的 N 要和dataDir下myid文件的内容一致。每台 ZooKeeper 的myid文件写自己的编号比如 zk1 写 1zk2 写 2。这个文件如果写错ZooKeeper 启动时会报My id not in the server list或者选主异常。tickTime默认 2000ms一般不用改。但如果集群跨机房部署网络延迟大initLimit和syncLimit要适当调大否则 Follower 同步超时会导致节点反复掉出集群。3.3 BookKeeper 配置存储层的读写参数BookKeeper 是 Pulsar 的存储引擎消息以 Ledger 为单位写入。每个 Ledger 由多个 Bookie 共同存储通过 Quorum 机制保证可靠性。conf/bookkeeper.conf里核心参数# Bookie 对外暴露的地址 advertisedAddressbk1.example.com # BookKeeper 使用的 ZooKeeper 地址 zkServerszk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181 # Ledger 数据目录建议用独立磁盘 ledgerDirectoriesdata/bookkeeper/ledgers # Journal 目录建议用 SSD写入延迟直接影响消息发送延迟 journalDirectoriesdata/bookkeeper/journal # 写入 Quorum3 副本时2 个确认即算成功 writeQuorum3 ackQuorum2 ensembleSize3journalDirectories和ledgerDirectories分开配是常见做法。Journal 是预写日志每次写入都要 fsync对磁盘延迟极其敏感。如果 Journal 和 Ledger 共用一块机械盘写入性能会明显下降。我一般建议 Journal 放 SSDLedger 放普通盘。writeQuorum、ackQuorum、ensembleSize这三个参数决定了写入的可靠性和延迟。ensembleSize是每条 Ledger 使用的 Bookie 数量writeQuorum是实际写入的副本数ackQuorum是收到多少个确认就返回成功。3/2/3 的组合意味着3 个 Bookie 参与存储每条消息写 3 份收到 2 个确认就返回。这样允许 1 个 Bookie 挂掉不影响写入。3.4 Broker 配置连接客户端与路由Broker 是无状态的配置相对简单但有几个参数直接影响客户端体验# Broker 对外暴露的地址集群模式下必须改 advertisedAddressbroker1.example.com # ZooKeeper 地址 metadataStoreUrlzk:zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181 # BookKeeper 地址 bookkeeperMetadataServiceUrizk:zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181 # 允许客户端连接的端口 brokerServicePort6650 webServicePort8080 # 是否开启 Geo-replication enableGeoReplicationfalseBroker 启动后会往 ZooKeeper 注册自己客户端连接时先查 ZooKeeper 拿到 Broker 地址列表再直连 Broker。如果advertisedAddress配错客户端拿到错误地址后连接失败日志里会看到Failed to connect to broker或者Connection refused。enableGeoReplication默认关闭。如果要做跨机房复制需要开启并配置replicationClusters。这个功能在 2.9.1 里已经比较稳定但跨机房延迟对复制效率影响很大建议先在同机房验证。4. 避坑排查那些让你半夜爬起来看日志的问题4.1 启动报端口冲突Address already in use现象执行bin/pulsar standalone后立即报错退出日志显示java.net.BindException: Address already in use。原因Pulsar 单机模式需要 2181ZooKeeper、3181BookKeeper、6650Broker、8080Web 管理四个端口。其中任何一个被占用都会导致启动失败。常见的是 2181 被已有的 ZooKeeper 占用或者 8080 被 Tomcat 之类的 Web 服务占用。解决先用lsof -i:2181、lsof -i:8080逐个确认占用进程。如果是无关进程停掉或改端口。如果确实需要保留已有 ZooKeeper可以改conf/standalone.conf里的zookeeperServers和configurationStoreServers指向已有 ZooKeeper但要注意 Pulsar 会在上面创建自己的 znode 路径不要和其他系统混用根路径。4.2 客户端连不上 BrokeradvertisedAddress 的坑现象Broker 启动正常本地pulsar-admin能操作但远程客户端连接时报Connection refused或Failed to connect to broker。原因advertisedAddress配成了localhost。Broker 告诉客户端「连我 localhost:6650」远程客户端拿到这个地址后连的是自己的 localhost自然连不上。解决把conf/broker.conf里的advertisedAddress改成 Broker 所在机器的实际 IP 或可解析的主机名。改完重启 Broker。验证方法是pulsar-admin brokers list看返回的地址是不是实际地址。4.3 BookKeeper 写入超时Journal 磁盘性能不足现象消息发送延迟忽高忽低Broker 日志里出现Bookkeeper write timeout或Ledger creation failed。原因BookKeeper 的 Journal 写入需要 fsync如果 Journal 目录放在机械盘或者和 Ledger 共用一块盘写入延迟会飙升。尤其是在消息量大的时候Journal 写入成为瓶颈。解决把journalDirectories指向 SSD 盘。如果条件有限至少把 Journal 和 Ledger 分到不同物理盘上。另外可以适当调大journalSyncData的批量大小但不要为了性能关掉 fsync否则断电会丢数据。4.4 Topic 创建失败命名空间策略限制现象客户端发送消息时报Topic not found或Authorization failed但 Topic 明明已经创建了。原因Pulsar 的 Topic 归属命名空间命名空间有权限策略和创建策略。如果allowAutoTopicCreation设为false且没有显式创建 Topic客户端发送时会失败。另外如果命名空间的权限没配好即使 Topic 存在也会报授权失败。解决先用pulsar-admin topics list tenant/namespace确认 Topic 是否存在。不存在就显式创建pulsar-admin topics create persistent://tenant/namespace/topic。权限问题用pulsar-admin namespaces grant-permission给客户端角色授权。4.5 集群节点频繁掉出ZooKeeper 会话超时现象集群运行一段时间后某个 Broker 或 BookKeeper 节点频繁掉出集群又重新加入日志里出现Session expired或Connection loss。原因ZooKeeper 的tickTime、initLimit、syncLimit配置和实际网络延迟不匹配。跨机房部署时尤其常见网络抖动导致心跳超时ZooKeeper 认为节点挂了触发重新选主。解决适当调大tickTime比如从 2000 调到 4000同时按比例调大initLimit和syncLimit。另外检查 ZooKeeper 节点的 GC 日志长时间 Full GC 也会导致会话超时。如果跨机房考虑把 ZooKeeper 集群部署在同机房Broker 和 BookKeeper 跨机房访问。5. 进阶技巧用 Pulsar Admin 做日常运维与验证5.1 集群健康检查的几条命令部署完之后怎么确认集群真的健康我一般按这个顺序走一遍# 1. 查看 Broker 列表确认所有 Broker 都注册了 bin/pulsar-admin brokers list cluster-name # 2. 查看 BookKeeper 集群状态 bin/pulsar-admin bookies list # 3. 查看租户和命名空间 bin/pulsar-admin tenants list bin/pulsar-admin namespaces list tenant # 4. 创建 Topic 并测试生产消费 bin/pulsar-admin topics create persistent://public/default/test-topic bin/pulsar-client produce persistent://public/default/test-topic -m hello bin/pulsar-client consume persistent://public/default/test-topic -s test-sub -n 1pulsar-admin brokers list返回的地址列表要和实际部署一致。如果少了某个 Broker说明它没注册成功去查那台 Broker 的日志。pulsar-admin bookies list会返回所有 Bookie 的地址和状态如果有 Bookie 显示down检查那台机器的 BookKeeper 进程和 Journal 磁盘。5.2 用 Pulsar Client 做端到端验证命令行工具验证完基本功能后建议用客户端代码做一次端到端测试确认生产消费链路没问题# Python 客户端示例需要先安装 pulsar-client # pip install pulsar-client2.9.1 import pulsar # 连接 Broker注意地址要和 advertisedAddress 一致 client pulsar.Client(pulsar://broker1.example.com:6650) # 创建生产者 producer client.create_producer(persistent://public/default/e2e-test) # 发送 10 条消息 for i in range(10): producer.send((msg-%d % i).encode(utf-8)) print(Sent: msg-%d % i) # 创建消费者 consumer client.subscribe( persistent://public/default/e2e-test, subscription_namee2e-sub, consumer_typepulsar.ConsumerType.Shared ) # 接收消息 for i in range(10): msg consumer.receive() print(Received: %s % msg.data().decode(utf-8)) consumer.acknowledge(msg) client.close()这段代码做了三件事连接 Broker、发送 10 条消息、用 Shared 订阅模式消费 10 条消息。consumer_type设为Shared表示多个消费者可以共同消费同一个订阅适合队列场景。如果是流式场景需要每个消费者都收到全量消息用Exclusive或Failover。跑通之后可以进一步验证多租户隔离、消息 TTL、死信队列等特性。这些在 2.9.1 里都有对应的 Admin API 和客户端配置。5.3 一个容易忽略的细节消息去重与幂等Pulsar 支持消息去重Deduplication但需要显式开启。在命名空间级别配置# 开启命名空间的消息去重 bin/pulsar-admin namespaces set-deduplication public/default --enable # 查看去重状态 bin/pulsar-admin namespaces get-deduplication public/default开启后Broker 会为每个生产者分配一个唯一的 producer name并根据序列号去重。如果生产者发送重复序列号的消息Broker 会丢弃并返回确认。这个功能对网络重试导致的重复消息很有效但要注意去重状态是存在 Broker 内存里的Broker 重启后会丢失。如果需要跨重启的去重得靠 BookKeeper 的 Ledger 级别去重配置更复杂。从那以后我每次部署完 Pulsar 集群都会先跑一遍brokers list、bookies list、端到端生产消费这三步确认链路通了再往上叠业务。这套流程帮我省了不少半夜排查的时间。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?