简介:这是 Apache Pulsar 2.9.1 官方二进制发行包,面向消息中间件开发者和分布式运维人员,用于快速搭建消息队列环境,解决高吞吐、持久化与实时流处理需求。压缩包为 gz 格式,约 321.53MB,包含服务端二进制、客户端库、脚本等辅助工具,解压后可参考官方文档直接部署运行。已有151人学习下载,适合入门研究或生产预研。此版本利用 ZooKeeper 协调元数据,具备高可用与一致性,支持 Pub/Sub、多种订阅模式、BookKeeper 持久化及 Pulsar Functions 轻量计算,并可集成 Kubernetes,满足云原生场景。无论是学习架构还是实际调优,该包都能提供可直接使用的基础环境。
1. Pulsar 2.9.1 的二进制包,到底解决了谁的问题
很多刚接触 Apache Pulsar 的人,第一反应是去官网找源码包自己编译,结果搭 Maven、拉依赖、等编译,没等跑起来就先消耗了小半天。这个 bin.tar.gz 的存在,就是把「编译源码再部署」这条弯路直接抹平了。它把 Pulsar Broker、BookKeeper、ZooKeeper 相关的脚本和配置都打成了现成的二进制发行包,下载解压之后就能开始做节点规划、改配置、起服务,省下来的时间用来理解分布式消息系统本身的结构,比折腾编译环境有价值得多。
这个包的核心价值,是用一个 tarball 覆盖了「搭建一套可运行的 Pulsar 集群 + 客户端连通性验证」的全过程。它适合两类人:一类是要在测试环境或者单机环境快速搭一套 Pulsar,验证消息收发和延迟表现的人;另一类是想把 Pulsar 和现有 ZooKeeper 集群做整合、理解 Broker 与元数据存储之间关系的人。注意这里有个前提——Pulsar 2.9.1 对 ZooKeeper 的依赖是硬性的,元数据、协调、选主都靠它,这个包默认内置了 ZooKeeper 相关配置,但你要是对接外部集群,需要改的配置项不止一两个。
实际拆过这个包之后,我会从「包内结构」「配置改动」「启停顺序」「客户端验证」「最容易翻车的地方」这几个层面来聊,每一层都有具体的文件路径和参数可以对照。
2. 拆开 tarball:先看懂目录,再动配置
2.1 压缩包内部的结构长什么样
拿到apache pulsar 2.9.1 bin.tar.gz之后,先把包解开,看它顶层目录的构成。按 2.9.1 发行版的常规布局,解压后会得到一个类似apache-pulsar-2.9.1/的根目录,里面比较关键的几块是:bin/放启停脚本,conf/放所有 broker、bookkeeper、zookeeper、client 的配置文件,lib/放运行依赖的 jar,examples/放官方给的示例代码。目录本身不复杂,但conf/下的内容要花时间读。
我一般先跑一条命令看整体体积和文件数量,确认包完整:
tar -tzf apache-pulsar-2.9.1-bin.tar.gz | head -50 tar -tzf apache-pulsar-2.9.1-bin.tar.gz | wc -l第一条命令列出前 50 个条目,快速确认根目录名和 bin 目录里的脚本是否齐全;第二条统计文件总数,用来判断有没有明显的截断或缺失。如果文件总数少于预期,大概率下载不完整或者镜像同步过程中出了问题,这种包不要继续用,直接换源重下。
解压之后,bin/下最常碰的是pulsar、pulsar-admin、pulsar-client。pulsar是服务端入口,启动 broker、standalone、zookeeper 都走它;pulsar-admin是做管理操作的 CLI;pulsar-client是命令行消息收发工具。这三个脚本覆盖了「起服务、做管理、验消息」三条核心路径,后面所有操作基本都在用它们。
2.2 单机模式先行:把配置先跑通
单机模式适合第一次验证这个包能不能用,命令如下:
bin/pulsar standalone启动后,Pulsar 会自动拉起一个内嵌的 ZooKeeper 和 BookKeeper,不需要你手动去启额外的服务,这是 standalone 模式的设计目标——把依赖都揉进一个进程里。这时注意观察启动日志里的端口信息:Broker 服务默认监听 8080 端口(HTTP),客户端连接默认走 6650 端口(TCP),ZooKeeper 默认 2181。这三个端口要保证不被占用,否则启动会失败或者客户端连不上。
我在第一次验证时通常会确认一下 Java 环境,因为 Pulsar 2.9.1 要求 JDK 8 或 11,版本不对会出现类加载错误。运行java -version看当前版本,然后启动 standalone,日志刷到messaging service is ready这种标志性信息就说明 broker 起来了。
验证单机模式是否正常,最好的方式是直接跑 CLI 收发消息:
bin/pulsar-client produce -m "hello, pulsar" -n 5 my-topic bin/pulsar-client consume -n 5 my-topic这样能在几十秒内确认 Broker 的写入和读取链路通不通。这里有一个容易忽略的点:my-topic这个 topic 名不需要提前创建,Pulsar 默认允许自动创建 topic,所以生产端发完消息,消费端直接连同一个名字就能收到。
2.3 集群模式配置:ZooKeeper 相关的三个改动点
单机模式跑通之后,进入真正的集群部署时,配置的改动量会比想象中大。conf/standalone.conf和conf/broker.conf是两套不同的配置,前者只服务单机,后者服务集群。用集群模式时,必须改broker.conf里的三类配置。
第一类是 ZooKeeper 连接串。默认配置里写的是zkServers=localhost:2181。一旦放到多节点,这里就要改成由逗号分隔的 ZooKeeper 节点列表,比如zkServers=zk1:2181,zk2:2181,zk3:2181。这个配置项决定 broker 去哪里找元数据,改错会导致 broker 一直在「加载元数据失败-重启」的状态里打转。
第二类是 Broker 自身地址相关的配置。advertisedAddress和advertisedListeners这两个参数是给客户端和集群内其他组件做地址发现用的,如果配置的是localhost,外部客户端即使能连到机器 IP,也无法完成路由。我一般会显式写成内网 IP,比如advertisedAddress=192.168.1.10,避免出现「Broker 起来了但客户端连上就被断」的怪问题。
第三类是 BookKeeper 元数据。BookKeeper 的元数据也存放在 ZooKeeper 里,但存放路径独立,配置项是metadataStoreUri。如果打算把 Pulsar 和已有的 ZooKeeper 集群共用,但希望 BookKeeper 和 Pulsar 的元数据在 znode 上分层隔离,这里就需要显式设置路径,常见做法是:
metadataStoreUri=zk:zk1:2181,zk2:2181/pulsar/pulsar 这个路径区分了 Pulsar 元数据和 ZooKeeper 自身的其他数据,而且多个环境共用同一个 ZooKeeper 集群时,这种路径隔离是做多环境必要的。注意metadataStoreUri在 2.9.1 里同时承担了 Pulsar 元数据和 BookKeeper 元数据两层指向,不熟悉的人容易只改zkServers而漏掉它,导致 broker 起得来、BookKeeper 却一直找不到 ledger。
3. 搭建集群:从 ZooKeeper 到 Broker 的启动顺序与检查
3.1 谁先谁后:ZooKeeper、BookKeeper、Broker 的依赖关系
如果要把这个包用于多节点部署,启动顺序不能乱。Pulsar 的依赖链是 ZooKeeper 在最底层,BookKeeper 依赖 ZooKeeper,Broker 同时依赖 ZooKeeper 和 BookKeeper。顺序不对时,报错信息也不一样,看到的现象会让人误判。
我的启动顺序是:先启动外部 ZooKeeper(如果是自建的话),然后启动 BookKeeper,最后启动 Broker。用这个包自带的脚本做集群模式启动时,各节点分别执行:
bin/pulsar zookeeperZooKeeper 起来之后,确认 2181 端口能通,再用bin/bookkeeper脚本启动 BookKeeper bookie。注意这里不能直接跑bin/pulsar bookie,因为 2.9.1 版对 bookie 的启动脚本封装路径和 bin 下其他服务不一样,用bin/pulsar bookie容易报找不到类。跑到这一步,日志里能刷出 bookie 注册成功的记录。
最后启动 Broker,执行:
bin/pulsar broker观察日志里是否出现broker successfully started或者类似含义的信息。没有这个信息就去查前一个节点的日志,别急着改 broker 配置。
3.2 用 admin CLI 检查集群健康状态
服务全部起来后,不要急着发消息,先用pulsar-admin做三个健康检查,确认集群状态可信。命令分别是:
bin/pulsar-admin clusters list bin/pulsar-admin brokers list my-cluster bin/pulsar-admin namespaces list publicclusters list用来确认集群元数据是否注册到 ZooKeeper;brokers list my-cluster用来确认当前跑起来的 broker 节点都被正确登记;namespaces list public则确认默认命名空间存在。这三条命令如果都返回正常,说明 broker 到 ZooKeeper 的元数据链路是通的,后续做 topic 操作才有底气。
其中一个容易忽略的细节是:brokers list后面跟的集群名是配置文件clusterName里定义的值,不是随便填的。默认配置里一般写的是my-cluster,和pulsar-admin brokers list my-cluster里的参数要一致。有人在这里填了别的名字,admin 工具返回空列表,误以为集群没起来,其实只是名字没对上。
3.3 手动建 namespace 和 topic:避开自动创建的坑
虽然 Pulsar 默认允许 topic 自动创建,但生产环境里我一般会关掉自动创建,改为显式创建。理由是自动创建会把 namespace、topic 的元数据都写进 ZooKeeper,后面想调整策略时,这些默认数据会成为干扰项。关闭自动创建的配置在 broker.conf 里:
allowAutoTopicCreation=false allowAutoSubscriptionCreation=false显式创建 namespace 和 topic 的命令如下:
bin/pulsar-admin namespaces create my-tenant/my-namespace bin/pulsar-admin topics create persistent://my-tenant/my-namespace/my-topic注意 topic 的完整名字里带persistent://前缀,这是 Pulsar 的 topic 域名格式的一部分。用 CLI 创建之后,再用pulsar-admin topics list my-tenant/my-namespace确认 topic 已存在,避免后续客户端因为访问不存在的 topic 而报错。
4. 客户端接入:参数选型与连接配置
4.1 Java 客户端:三个重要的构造参数
这个发行包不包含客户端源码,但自带的lib/目录里有编译好的 client jar,可以直接拿来做 Java 客户端的依赖。测试客户端时,通常用 Maven 引入对应版本的 client 依赖,版本号要匹配 2.9.1,而不是随意拉最新版。
Java 客户端连接 Pulsar 时的核心参数:
PulsarClient client = PulsarClient.builder() .serviceUrl("pulsar://192.168.1.10:6650") .operationTimeout(30, TimeUnit.SECONDS) .build();serviceUrl用的是 pulsar 协议地址,走 6650 端口,这个地址写的是 Broker 的advertisedAddress对应的 IP。operationTimeout设置的是元数据操作超时,比如 topic lookup、订阅查找这类动作,设得太短会导致集群稍忙时客户端直接超时。builder 里的ioThreads也可以按需调,默认值偏保守,高吞吐场景可以往上加。
4.2 Python 客户端:关注版本兼容
Python 客户端接入时,pulsar-client这个 pip 包的版本要和 broker 版本保持一致,否则可能出现认证相关字段不兼容的问题。最典型的例子是 2.9.x 的 broker 配 3.x 的 Python client,在 token 认证场景下会报一些奇奇怪怪的字段缺失错误。
基础收发逻辑的代码:
import pulsar client = pulsar.Client('pulsar://192.168.1.10:6650') producer = client.create_producer('persistent://my-tenant/my-namespace/my-topic') producer.send('hello'.encode('utf-8')) client.close()send方法的入参是 bytes,字符串要手动编码。创建 producer 时会触发一次 topic lookup,如果 broker 地址配置不对,这里会直接抛异常。
4.3 连接串版本:pulsar://、http:// 和 https:// 的适用场景
连接串的协议前缀不是随便选的。服务端 8080 端口对应的是 HTTP 管理接口,客户端连接用pulsar://是走二进制协议,更高效。只有在使用 Pulsar Proxy 或者走 HTTP 协议做某些受限场景时,才会用http://前缀。
本地测试时最容易犯的错是把pulsar://localhost:6650和http://localhost:8080混用。http://是给pulsar-admin做 REST 调用用的,让客户端用这个地址去收发消息,要么连不上,要么只能做管理操作做不了消息读写。
5. 避坑指南:这个包最常见的五个坑
5.1 启动失败,日志出现NoSuchMethodError
现象:执行bin/pulsar standalone之后,进程启动几秒就退出,日志里有NoSuchMethodError或ClassNotFoundException。
原因:最常见的是 JDK 版本不匹配。Pulsar 2.9.1 依赖 Java 8 或 11,如果在 Java 17 环境里跑,部分依赖库的反射调用会直接崩,报错位置往往在 Netty 或者 Protobuf 相关类上。
解决:把JAVA_HOME指到 JDK 8 或 JDK 11,重新执行启动命令。确认方式:
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 export PATH=$JAVA_HOME/bin:$PATH java -version5.2 Broker 起来了,但客户端连接后被断开
现象:Broker 日志显示正常,客户端create producer也成功,但一发送消息就超时或连接被重置。
原因:advertisedAddress配置成了localhost,broker 在返回数据地址时把localhost给了客户端,而客户端并不在本机,自然连不上。
解决:把 broker.conf 里的advertisedAddress改成内网 IP,避免用 localhost。改动后重启 broker。
5.3 BookKeeper 一直报 ledgers 目录无法创建
现象:BookKeeper 启动后报 IO 异常,提示 ledger 存储路径不存在或没有写权限。
原因:默认配置里journalDirectory和ledgerDirectories指向的目录未预先创建,或者部署用户对这些路径没有写权限。
解决:提前创建数据目录并授权:
mkdir -p /data/pulsar/journal /data/pulsar/ledgers chown -R pulsar:pulsar /data/pulsar5.4 两个节点能互相 ping 通,但跨节点复制失败
现象:双节点集群做好之后,一个节点生产的消息,另一个节点消费不到。
原因:问题最常见的不是 Pulsar 本身,而是 ZooKeeper 集群的节点列表里用了localhost,导致各节点看到的 ZooKeeper 地址是各自本机,实际上连到了同一个节点。
解决:所有 ZooKeeper 配置里的连接串都用主机名或内网 IP,不要用 localhost。同时确认/etc/hosts里主机名解析正常。
5.5 standalone 模式正常,但集群模式起不来
现象:bin/pulsar standalone一切正常,但切换成 broker 模式后启动失败,日志提示 metadata store 不可用。
原因:standalone 用了内置的 ZooKeeper 和元数据路径,而集群模式用的是外部 ZooKeeper,元数据路径不一致。
解决:明确区分两套配置,standalone 改standalone.conf,集群模式改broker.conf,不要混用。集群模式下确认metadataStoreUri指向的外部 ZooKeeper 是已经启动并写入过集群元数据的,空集群直接启 broker 会有问题。
6. 验证完整链路:从生产到消费的一次全流程走查
链路验证这一步,我会在生产环境第一次交付前强制跑一遍。整个过程不以「启动成功」为终点,而是以「消息成功消费且确认 offset 提交」为通过标准。
用自带的 CLI 做循环验证:
bin/pulsar-client produce -m "test message" -n 10 persistent://my-tenant/my-namespace/verify-topic bin/pulsar-client consume -n 10 persistent://my-tenant/my-namespace/verify-topic这里用持久化 topic 前缀,确认走的是持久化存储链路,而不是内存模式。如果消费端退出码为 0,说明 10 条消息全部拿到。
接着做一次管理链路验证:
bin/pulsar-admin topics stats persistent://my-tenant/my-namespace/verify-topic这个命令会返回 topic 的生产速率、消费速率、存储大小等统计指标。看到msgRateIn和msgRateOut不为 0,说明链路不只在 CLI 层通,底层指标也在正常累计。
如果需要同时验证多个消费者组隔离,可以开两个消费端分别指定不同的 subscription,命令:
bin/pulsar-client consume -n 5 -s sub-a persistent://my-tenant/my-namespace/verify-topic bin/pulsar-client consume -n 5 -s sub-b persistent://my-tenant/my-namespace/verify-topic两个 subscription 各收到完整的消息集,说明订阅模型的隔离没问题。如果两个订阅收到的消息数量不一致,说明出在 subscription 的创建或者 broker 的消息分发策略上,常见原因是自动创建的 subscription 没有显式指定类型,默认的Exclusive模式限制了第二个消费者接入。显式建订阅用:
bin/pulsar-admin topics create-subscription persistent://my-tenant/my-namespace/verify-topic -s sub-c从那以后,我每次部署完 Pulsar 都会强制走一遍这个验证流程,而不是看完 broker 日志就算收工。这套流程十次里能拦下两三次配置上的疏漏,尤其是advertisedAddress和 metadataStoreUri 这类「改错不报错、跑起来才出错」的项。希望你也能在交付前用同样的标准过一遍,省得在客户现场拿着日志一处一处猜。
本文还有配套的精品资源,点击获取