简介:Apache Pulsar 2.9.1 二进制分发压缩包,面向需要在生产或测试环境部署消息中间件的后端、运维与云原生开发人员,目标是省去源码编译和依赖构建,解压配置后即可启动服务使用。包内包含 Pulsar 服务端可执行程序、客户端库、常用运维脚本与辅助工具,整体大小约 321.53MB;由于上游未提供文件清单,暂不具体列举文件数量与格式。Pulsar 在 ZooKeeper 协助下管理主题、分区与集群元数据,配合 BookKeeper 实现高可用、低延迟的消息持久化;同时支持发布/订阅模型、共享/独占/故障转移等订阅类型,并提供分层存储与 Pulsar Functions,便于不常访问的历史数据迁移到低成本层,也能在消息平台上直接处理流数据。其分布式与云原生架构适合接入 Kubernetes 等容器环境,方便快速扩展与容错。已有 150 人学习或下载,适合希望直接上手体验 Pulsar 2.9.1 核心能力的使用者。 盯上apache pulsar 2.9.1 bin.tar.gz这个包的人,我猜基本是两类:一类是团队正在做技术选型,拿着 Pulsar 和 Kafka 来回对比,需要先拉个实例跑起来看看;另一类是生产环境已经定了 Pulsar,要在测试环境搭一套集群做压测或者排障。不管你是哪类,这个带bin.tar.gz后缀的二进制发行包都是最直接的入手点——不需要编译源码,不需要折腾 Maven 或 Gradle,解压就能跑。这篇文章就围绕它,把版本怎么选、包怎么装、单机和集群怎么启动、踩过的坑怎么排,一层层讲清楚。
1. 版本选型:为什么 2.9.1 值得用
1.1 2.9.x 系列的历史定位
Apache Pulsar 的版本节奏不算快,但每个大版本之间的差异非常明显。2.9.x 这个系列在整个 Pulsar 演进里属于一个承上启下的位置:它把 2.8 引入的pulsar-client新 API 稳定了下来,同时对transaction功能做了大量补全,2.9.1 作为 2.9 分支的修复版本,重点解决了一批 broker 内存泄漏和 BookKeeper 客户端写入超时的问题。
你在生产环境选版本时,我个人的建议是别追最新,也别停在太老的版本。2.9.1 的定位是“稳定修复版”,它没有大版本的激进新特性,但把 2.9.0 的坑基本都填平了。对很多只需要消息队列、延迟队列、消费订阅这些核心能力的项目来说,这是一个性价比很高的选择。如果你后面要升级到 2.10 或 3.x,从 2.9.1 起步的迁移路径也相对平滑,不会像从 2.7 跳 3.x 那样遇到配置项大改。
1.2 bin.tar.gz 和其他发行包的区别
Apache Pulsar 官方在 GitHub Releases 和 Apache 镜像站上会同时提供几种包,最常见的是:
apache-pulsar-2.9.1-bin.tar.gzapache-pulsar-2.9.1-src.tar.gz- 以及各连接器(connector)的独立压缩包
bin.tar.gz的意思就是已经编译好的二进制发行包,里面带着bin/、conf/、lib/、examples/这些目录。你不需要安装额外的构建工具,只需要一个 JDK 环境就能启动。src.tar.gz则是最新源码,需要自己用 Maven 构建,还得处理依赖下载,一般是为了二次开发或者定制才去碰它。
我实际上下载部署过很多次,强烈建议绝大多数场景直接选bin.tar.gz。它甚至不需要机器上有 Maven,省掉了很多网络和依赖上的麻烦。另外,如果你在公司内网部署,记得提前下载好包传到目标机器,因为部分网络环境直接访问 Apache 镜像站会比较慢,这一点后面我会再提。
2. 从下载到单机启动:完整实操过程
2.1 下载、校验和解压
Apache Pulsar 的下载地址有官方镜像站,也有 GitHub Releases 的附件。以下命令以 Linux 环境为例,把2.9.1的二进制包下载到/opt并解压:
cd /opt wget https://archive.apache.org/dist/pulsar/pulsar-2.9.1/apache-pulsar-2.9.1-bin.tar.gz # 强烈建议校验 SHA-512 wget https://archive.apache.org/dist/pulsar/pulsar-2.9.1/apache-pulsar-2.9.1-bin.tar.gz.sha512 sha512sum -c apache-pulsar-2.9.1-bin.tar.gz.sha512 # 解压 tar -zxvf apache-pulsar-2.9.1-bin.tar.gz mv apache-pulsar-2.9.1 /opt/pulsar校验这一步很容易被忽略,但这是供应链安全的第一道防线。Apache 项目发布的包都带.sha512或.asc签名,你至少要做一次哈希校验,确认下载过程中没有出现文件损坏或被中间人替换。我见过有人跳过校验,结果解压时就报错,折腾半天才发现是包不完整。
解压完成后,看一眼目录结构:
cd /opt/pulsar ls -l你会看到bin、conf、data、examples、lib、logs这几个关键目录。其中bin目录下的pulsar脚本是核心入口,conf目录里放着所有配置文件,包括standalone.conf、broker.conf、zookeeper.conf等。
2.2 单机模式启动与验证
单机模式适合开发测试和功能验证,它会在一个进程里同时拉起 ZooKeeper、BookKeeper 和 Broker 三个角色。Pulsar 的 standalone 模式不需要你做任何额外配置,直接执行:
cd /opt/pulsar bin/pulsar standalone首次启动会初始化元数据,然后监听8080(HTTP 服务端口)和6650(客户端通信端口)。看到日志里出现pulsar-service started或者类似信息,说明启动成功。
接着我们可以通过命令行工具验证一下:
# 创建名为 my-topic 的 topic bin/pulsar-admin topics create persistent://public/default/my-topic # 生产一条消息 bin/pulsar-client produce my-topic --messages "hello-pulsar-2.9.1" # 消费这条消息 bin/pulsar-client consume my-topic --subscription-name my-sub --num-messages 1如果你能在消费端看到hello-pulsar-2.9.1,整个链路就通了。这里特别注意,pulsar-client consume默认会一直阻塞等待新消息,加--num-messages 1可以只消费一条后退出,适合测试。
2.3 Java 环境和内存要求
Pulsar 2.9.1 官方要求 Java 8 或 11,我实际用下来 JDK 11 的稳定性最好。确认方式:
java -version如果机器上有多套 JDK,务必确认默认java命令指向的版本。Pulsar 启动脚本默认读取JAVA_HOME环境变量,如果设置不对,会直接抛UnsupportedClassVersionError。
内存方面,standalone 模式默认的堆内存配置不算大,但如果你的机器内存少于 4G,建议修改conf/pulsar_env.sh里的PULSAR_MEM配置,防止 BookKeeper 和 broker 抢内存导致操作系统 OOM。我通常这样设置:
PULSAR_MEM="-Xms512m -Xmx1g -XX:MaxDirectMemorySize=1g"需要说明的是,这只是微调,不要贸然把堆内存调到物理内存以上,否则系统 Swap 会拖垮性能。
3. 从单机走向集群:部署经验和配置避坑
3.1 最小集群的角色划分
生产环境很少用 standalone,通常至少需要三个角色独立部署:ZooKeeper、BookKeeper、Broker。有些团队还会把 BookKeeper 分出一组专用于 system topic 的节点,但对起步阶段来说,一个最小集群可以由 3 台机器组成:每台机器同时跑一个 ZooKeeper、一个 BookKeeper、一个 Broker,这是比较省机器的方案。如果资源允许,我建议 ZooKeeper 单独 3 台,BookKeeper 和 Broker 混合部署,因为 ZooKeeper 节点对磁盘 IO 的抖动很敏感。
3.2 关键配置项
在conf/broker.conf里,最重要的几个配置是:
zookeeperServers=zk1:2181,zk2:2181,zk3:2181 configurationStoreServers=zk1:2184,zk2:2184,zk3:2184 advertisedAddress=broker-ip bindAddress=0.0.0.0advertisedAddress一定要填客户端能够访问到的地址,很多部署问题都是因为这里填成了localhost或者内网 DNS 无法解析的主机名,导致客户端连接 broker 失败。
BookKeeper 的配置在conf/bookkeeper.conf,关键项是:
zkServers=zk1:2181,zk2:2181,zk3:2181 journalDirectory=/data/pulsar/bookkeeper/journal ledgerDirectories=/data/pulsar/bookkeeper/ledgers这里我强烈建议把journalDirectory和ledgerDirectories放到数据盘,不要放系统盘。BookKeeper 的 journal 是同步写盘,对磁盘延迟非常敏感,用 SSD 和机械盘跑出来的写入性能相差很大。我踩过这个坑:一开始图省事把数据放在默认目录,结果 Topic 数量一多,IO 等待直接飙高,broker 日志里全是 Bookie 写入超时。
集群启动顺序也有讲究,必须先 ZooKeeper,再 BookKeeper,最后 Broker。反过来启动,Broker 会因为找不到 ZooKeeper 而反复重试,日志刷屏不说,恢复时间也会被拖长。
3.3 用 systemd 管理 Pulsar 进程
手动用bin/pulsar启动进程,SSH 一断服务就没了,不适合生产。我一般会写 systemd unit 文件来托管。拿 Broker 举例:
[Unit] Description=Apache Pulsar Broker After=network.target zookeeper.service bookkeeper.service [Service] Type=simple User=pulsar Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk ExecStart=/opt/pulsar/bin/pulsar broker Restart=on-failure RestartSec=10 LimitNOFILE=65536 [Install] WantedBy=multi-user.target把这个文件放在/etc/systemd/system/pulsar-broker.service,然后执行:
systemctl daemon-reload systemctl enable pulsar-broker systemctl start pulsar-brokerLimitNOFILE=65536这一项经常被忽略。Pulsar 作为消息系统,会打开大量 socket 和文件句柄,系统默认的 1024 限制会在高连接数时直接导致服务崩溃。
4. 常见问题与排查技巧实录
4.1 端口被占用导致启动失败
Pulsar 启动时报Address already in use,最典型的是8080或者6650被占用。排查方式:
ss -lntp | grep 8080如果确认是旧进程残留,直接 kill 后重启。还有种隐蔽情况:多个 Pulsar 实例共用一台机器,一个配置里漏改了监听端口,两个进程就会冲突。我在测试环境经常同时起多个 standalone,每次都记得改conf/standalone.conf里的webServicePort和brokerServicePort。
4.2 客户端连不上 broker
客户端连不上时,不要第一时间怀疑防火墙,先把 broker 日志拉出来看一眼。常见原因有三个:
advertisedAddress配置错误,客户端拿到的是 broker 内部地址,连不通。- 客户端网络到 broker 的
6650端口被防火墙或安全组拦截。 - Broker 处于 starting 状态,还没有完成初始化,客户端连接直接被拒绝。
第三种情况最容易误导人,因为进程明明在,端口也监听着,但 broker 内部的 namespace 初始化没完成。看日志会发现类似There is no topic policy或者Failed to load namespace报错,等 10-20 秒再重试就好。
4.3 Pulsar 和 Kafka,到底谁资料更丰富
选型阶段很多人会纠结这个问题。老实说,Pulsar 的中文资料数量确实不如 Kafka 多,Kafka 入华早,社区沉淀了大量文章和博客。但 Pulsar 的官方文档完整度很高,Apache Pulsar 的官方站点、GitHub 仓库、邮件列表,以及 StreamNative 的中文社区文档,都能找到足够上手的资料。从我实操的感受来看,Pulsar 的架构设计比 Kafka 更复杂,学习曲线陡一些,但官方提供的pulsar-admin、pulsar-client命令行工具使用起来非常顺手,很多管理操作不需要额外开发代码。资料少不是主要障碍,难的是你对底层 BookKeeper 的认知,这块需要多读官方文档。
5. 深入解读 Message ID:为什么是messageid|28077:20854:0
5.1 Ledger ID 和 Entry ID:Pulsar 消息的唯一坐标
有朋友看到messageid|28077:20854:0这种格式,会困惑这串数字到底怎么来的。其实 Pulsar 的消息 ID 由三部分组成:ledgerId:entryId:partitionIndex(部分场景还会带上batchIndex,但 API 层面最常见的就是这三个字段)。在 Pulsar 的底层存储里,数据按 Ledger(分段)组织,一个 Ledger 是一个连续的 Entry 序列。每条消息写入时,都会被分配一个(ledgerId, entryId)二元组作为物理位置。
拿28077:20854:0来说,28077是 ledger ID,20854是 entry ID,最后一个0表示这条消息来自主题的 0 号分区。第一个28077前面的messageid|只是客户端打印时方便识别的前缀,不是 ID 的一部分。
这也解释了为什么 Pulsar 的 Offset 不像 Kafka 那样是一个单调递增的整数,而是一个“坐标”。由于消息分布在不同 Ledger 里,你不能简单用一个大数去描述“消费位置”。
5.2 与 Kafka Offset 的对比
Kafka 的消息位置就是 partition 内的一个长整型 offset,消费者保存的是“下一个要消费的位置”,实现起来很直观。Pulsar 用(ledgerId, entryId)来表示位置,好处是存储层天然支持 Ledger 级别的数据管理和恢复,坏处是如果你想在代码里比较两个 Message ID 的大小,不能直接比长整型,要写msgId.compareTo(anotherMsgId)。好在官方 Java 客户端已经封装好了,你只要用MessageId接口,不需要自己解析字符串。
5.3 看 Message ID 能发现什么
排查消息积压或者消费卡住时,Message ID 非常有用。客户端日志里会打印当前消费到的位置,如果你发现 ID 长时间不变,说明消费端已经停止拉取。而ledgerId增长幅度很大时,说明系统在持续产生数据,broker 不断创建新的 ledger。如果想知道某条消息到底从哪来,还可以用pulsar-admin topics peek-messages工具直接查看指定位置的原始消息内容。
bin/pulsar-admin topics peek-messages \ --topic persistent://public/default/my-topic \ --subscription my-sub --count 1这个命令会把消息体、消息 ID 和 publish time 一起打出来,排查时非常有价值。
6. 部署后的日常维护建议
最后分享几条我在实际操作中提炼出来的维护经验。Pulsar 2.9.1 不是那种解压缩就一劳永逸的系统,它的日常健康检查至少要关注三块:ZooKeeper 的节点状态、BookKeeper 的磁盘使用率、Broker 的 GC 情况。
BookKeeper 的磁盘容量是第一个容易爆的。Pulsar 的消息数据默认不会自动过期,如果没有设置 topic 的retention策略,磁盘会被持续占满。建议上线前就规划好 retention 和 ttl,用pulsar-admin namespaces set-retention给 namespace 设置大小或时间上限。
GC 方面,观察 broker 进程的堆内存使用曲线,如果老年代持续增长且回收不掉,优先怀疑是否有消费者长期不提交 ack,导致 broker 积压了太多未确认消息。管理端可以用pulsar-admin topics stats查看订阅积压情况:
bin/pulsar-admin topics stats persistent://public/default/my-topic重点关注msgBacklog和blockedSubscriptionOnUnackedMessages这两个字段,如果积压持续上涨,就要去排查消费者逻辑了。
2.9.1 是我个人用下来比较顺手的版本,它在稳定性和新特性之间找到了一个平衡点。部署这事,照着上面这些步骤来,单机验证半天内能跑通,集群配上 systemd 加监控,基本可以安心交给运维。后面如果因为业务需求要到 3.x,再把配置迁移和新特性吃透,那是另一个话题了。
本文还有配套的精品资源,点击获取