Pulsar分布式集群+图形化运维实战指南

Pulsar分布式集群+图形化运维实战指南 1. 项目概述为什么Pulsar集群必须配图形界面——从命令行到可视化的实战跃迁Pulsar消息队列在金融、物联网和实时数仓场景里越来越常见但很多人卡在第一步装完standalone模式后一上分布式集群就懵了。不是报错ZooKeeper连接超时就是BookKeeper ledger写入失败更别说查个topic消费延迟、看个broker负载水位——全靠pulsar-admin topics stats这种命令一行行敲眼花缭乱还容易漏关键指标。我去年帮一家做车联网数据中台的客户做压测他们用的是3节点Pulsar集群运维同学每天要手动跑8个脚本查broker内存、bookie磁盘、topic分区积压、订阅确认延迟光是整理日报就得两小时。后来我们硬是把Pulsar admin manager图形界面搭起来现在点几下鼠标就能看到整个集群的健康拓扑图某个broker CPU飙到95%时界面自动标红告警点进去直接看到是哪个topic的backlog暴涨导致的。这才是生产环境该有的样子。你不需要成为ZooKeeper专家才能管好Pulsar但你必须有一套能“看见”系统状态的工具。本文讲的不是教科书式的安装步骤而是我在6个不同客户现场踩过坑、调过参、重装过17次后总结出的可落地、可监控、可排障的Pulsar分布式集群图形界面完整方案。重点不是“怎么装”而是“为什么这么装”——比如为什么ZooKeeper必须奇数节点为什么BookKeeper的journal目录绝不能和ledger目录放在同一块SSD为什么Pulsar Manager的数据库选PostgreSQL而不是默认H2这些细节决定了你的集群是稳定运行半年还是上线三天就OOM崩溃。2. 整体架构设计与核心组件选型逻辑2.1 分布式集群不是“多装几台机器”而是分层解耦的精密协作很多人以为“分布式集群”就是把Pulsar broker、BookKeeper、ZooKeeper各装三台然后改改配置文件就完事了。实则不然。Pulsar的分布式能力本质是三层解耦ZooKeeper管元数据谁是谁、在哪、BookKeeper管持久化日志消息存哪、怎么备份、Broker管服务接入客户端连谁、怎么路由。这三层必须独立部署、独立扩容、独立监控。我见过最典型的错误是把ZooKeeper、BookKeeper、Broker全塞进同一台4核8G虚拟机结果ZooKeeper GC停顿导致BookKeeper心跳超时进而触发broker自动剔除整个集群雪崩。所以我们的设计原则第一条物理隔离资源独占。ZooKeeper节点只跑ZK进程BookKeeper节点只跑bookieBroker节点只跑broker不混部。第二条容量预估必须带余量。ZooKeeper不是越多越好3节点足够支撑500个topic、10万QPS的集群BookKeeper节点数决定写入吞吐上限每台bookie建议配置2块NVMe SSD一块journal一块ledger单节点写入能力实测可达120MB/sBroker节点数则取决于客户端连接数和topic数量每台broker承载2000个连接、500个topic是安全阈值。第三条网络拓扑必须扁平。所有节点必须在同一局域网内跨机房部署必须用专线且延迟2ms否则ZooKeeper会频繁触发leader选举。2.2 Pulsar Manager不是“锦上添花”而是生产级运维的刚需入口Pulsar官方提供的pulsar-admin命令行工具功能齐全但它是面向开发者的调试工具不是面向SRE的监控平台。它没有历史趋势图不能设置告警阈值无法做权限分级租户A看不到租户B的topic更没法一键导出集群拓扑。而Pulsar Manager正是为解决这些痛点而生。但它不是开箱即用的“绿色软件”其底层依赖一个关系型数据库存储配置和监控快照这就引出了关键选型问题用H2、MySQL还是PostgreSQLH2是嵌入式数据库轻量但不支持高并发仅适合单机测试MySQL社区版虽成熟但Pulsar Manager官方文档明确指出其对MySQL 8.0的JSON字段支持不完善会导致“集群健康状态”页面加载失败PostgreSQL 12则完美支持JSONB类型且自带时间序列扩展timescaledb我们实测在10万条监控记录下查询响应时间仍稳定在80ms以内。所以最终方案PostgreSQL作为Pulsar Manager后端数据库独立部署于一台4核16G服务器与Pulsar集群物理隔离但网络互通。这个选择背后是血泪教训——某客户曾用H2跑Manager第3天就因数据库锁表导致整个Web界面不可用重启后所有自定义告警配置丢失。2.3 standalone模式只是“玩具”真正的分布式必须直面ZooKeeper脑裂风险很多教程从bin/pulsar standalone开始这没错但极易误导新手。Standalone模式把ZK、BK、Broker全塞进一个JVM它绕过了所有分布式一致性协议根本测不出真实问题。比如ZooKeeper的tickTime参数在standalone里设成2000ms也无所谓但在3节点ZK集群里这个值必须严格满足initLimit 10 * tickTimesyncLimit 5 * tickTime否则follower节点同步日志超时就会被踢出集群。我们线上集群的tickTime固定为2000msinitLimit为20000syncLimit为10000这是经过200次压力测试验证的黄金组合。另一个致命陷阱是ZooKeeper的dataDir和dataLogDir必须分盘。dataDir存快照dataLogDir存事务日志后者是顺序写密集型IO如果和快照共用一块SATA盘日志写满会导致ZK服务假死。我们强制要求dataLogDir必须挂载到独立的NVMe SSD且预留空间不低于50GB。这些细节决定了你的集群是“能跑”还是“稳跑”。3. 核心组件安装与分布式集群搭建实操详解3.1 ZooKeeper集群3节点高可用部署的硬性规范ZooKeeper是Pulsar集群的“大脑”它的稳定性直接决定整个消息系统的生死。部署前必须确认三点所有节点时间同步NTP服务必须开启、主机名解析正确/etc/hosts必须静态映射IP和hostname、防火墙开放2181客户端端口、2888follower连接leader端口、3888leader选举端口。以三台服务器为例IP分别为192.168.1.10zk1、192.168.1.11zk2、192.168.1.12zk3hostname分别为zk1.example.com、zk2.example.com、zk3.example.com。首先下载ZooKeeper 3.8.3Pulsar 3.1推荐版本wget https://downloads.apache.org/zookeeper/zookeeper-3.8.3/apache-zookeeper-3.8.3-bin.tar.gz tar -xzf apache-zookeeper-3.8.3-bin.tar.gz mv apache-zookeeper-3.8.3-bin /opt/zookeeper创建数据目录注意dataLogDir必须独立mkdir -p /data/zk/data /data/zk/datalog chown -R pulsar:pulsar /data/zk核心配置/opt/zookeeper/conf/zoo.cfgtickTime2000 initLimit20000 syncLimit10000 dataDir/data/zk/data dataLogDir/data/zk/datalog clientPort2181 maxClientCnxns60 autopurge.snapRetainCount3 autopurge.purgeInterval1 server.1zk1.example.com:2888:3888 server.2zk2.example.com:2888:3888 server.3zk3.example.com:2888:3888关键点解析server.xhostname:2888:3888中的x必须是整数且每台机器的myid文件内容必须与之对应。在zk1上执行echo 1 /data/zk/data/myidzk2上执行echo 2 /data/zk/data/myidzk3上执行echo 3 /data/zk/data/myid。这个ID不是IP序号而是ZK集群内的唯一标识填错会导致节点无法加入集群。启动顺序有讲究必须先启zk1等zkServer.sh status返回Mode: leader后再启zk2最后启zk3。切忌同时启动否则可能触发多次leader选举。验证集群状态# 在任意节点执行 /opt/zookeeper/bin/zkServer.sh status # 正常应返回类似 # ZooKeeper JMX enabled by default # Using config: /opt/zookeeper/bin/../conf/zoo.cfg # Mode: follower # 或 leader, participant提示如果某节点始终显示Mode: standalone说明它没连上其他节点。检查/opt/zookeeper/logs/zookeeper.out90%的情况是/etc/hosts里hostname解析错误或防火墙未放行2888/3888端口。3.2 BookKeeper集群避免磁盘IO瓶颈的双盘分离实践BookKeeper是Pulsar的“硬盘”负责消息的持久化存储。它的性能瓶颈几乎100%在磁盘IO。我们坚持一个铁律journal目录和ledger目录必须分属两块物理磁盘。Journal是WALWrite-Ahead Log要求极致的顺序写性能Ledger是实际消息存储读写混合。若共用一块SATA盘journal写满会阻塞ledger写入导致broker报No available bookies错误。实测数据一块Intel Optane P5800X NVMe SSDjournal盘 一块三星PM1733 NVMe SSDledger盘单bookie写入吞吐达120MB/s若共用一块SATA盘吞吐骤降至18MB/s且延迟毛刺高达2s。部署BookKeeper 4.16.3与Pulsar 3.1兼容wget https://archive.apache.org/dist/bookkeeper/bookkeeper-4.16.3/bookkeeper-server-4.16.3-bin.tar.gz tar -xzf bookkeeper-server-4.16.3-bin.tar.gz mv bookkeeper-server-4.16.3 /opt/bookie创建目录结构假设journal盘挂载在/mnt/journalledger盘挂载在/mnt/ledgermkdir -p /mnt/journal /mnt/ledger /data/bookie chown -R pulsar:pulsar /mnt/journal /mnt/ledger /data/bookie核心配置/opt/bookie/conf/bk_server.conf# 基础配置 bookieId192.168.1.20:3181 # 当前bookie的IP和端口 zkServerszk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181 # 磁盘配置关键 journalDirectory/mnt/journal ledgerDirectories/mnt/ledger # 性能调优 numAddWorkerThreads32 numReadWorkerThreads32 # 内存配置根据机器内存调整 nettyMaxFrameSizeBytes5242880启动前必须格式化bookie仅首次/opt/bookie/bin/bookkeeper shell bookiesanity # 若返回Sanity test passed说明磁盘和ZK连接正常 /opt/bookie/bin/bookkeeper shell metaformat # 格式化元数据启动bookie/opt/bookie/bin/bookkeeper-daemon.sh start bookie验证bookie注册到ZK# 连ZK客户端 /opt/zookeeper/bin/zkCli.sh -server zk1.example.com:2181 # 查看bookie列表 ls /ledgers/available # 应返回类似 [192.168.1.20:3181, 192.168.1.21:3181, ...]注意BookKeeper的bookieId必须是IP:port格式不能是hostname。因为Pulsar broker通过IP直连bookieDNS解析失败会导致写入中断。我们曾因bookieId配置成bookie1.example.com:3181在DNS服务器宕机时整个集群消息写入停滞12分钟。3.3 Pulsar Broker集群配置文件里的12个关键参数解读Broker是Pulsar的“门面”它不存消息只负责路由、认证、协议转换。但它的配置错误率最高。以下是conf/broker.conf中必须修改的12个参数及其原理zookeeperServerszk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181为什么必须指向ZK集群地址而非单点。若写成localhost:2181broker只能连本机ZK无法感知集群元数据。brokerServicePort6650和webServicePort8080为什么6650是Pulsar二进制协议端口Java/Python客户端用8080是HTTP管理端口pulsar-admin用。生产环境必须修改默认端口避免冲突。clusterNamemy-pulsar-cluster为什么集群唯一标识所有broker必须一致否则无法组成集群。advertisedAddress192.168.1.30为什么这是broker告诉客户端“你该连谁”的IP。必须是客户端能直接访问的IP不能是localhost或内网VIP。若broker在Docker中此处必须填宿主机IP。brokerDeduplicationEnabledtrue为什么开启去重防止网络抖动导致的重复投递。但会增加内存开销需配合brokerDeduplicationMaxNumberOfProducers10000使用。managedLedgerDefaultEnsembleSize3,managedLedgerDefaultWriteQuorum3,managedLedgerDefaultAckQuorum2为什么这是BookKeeper写入策略。“3-3-2”表示消息写入3个bookie至少3个确认才成功至少2个ack才返回客户端。这是强一致性保障不可降低。defaultRetentionTimeInMinutes100807天为什么消息保留时间。设为0表示永不清除但磁盘会爆。必须根据业务SLA设定金融类通常7天IoT类可设为1天。maxMessageSize52428805MB为什么单条消息最大尺寸。Pulsar默认1MB但大文件传输场景需调大。注意客户端也必须同步配置此参数否则发送失败。functionsWorkerEnabledfalse为什么Pulsar Functions是计算框架生产环境建议关闭除非真要用。开启会占用大量CPU和内存影响消息吞吐。authenticationEnabledtrue和authorizationEnabledtrue为什么生产环境必须开启认证授权。否则任何知道IP的人都能发消息、删topic。我们用JWT令牌认证配置见后文。tlsEnabledInBrokertrue和tlsCertificateFilePath/path/to/broker.cert.pem为什么启用TLS加密传输。证书必须由可信CA签发自签名证书需在客户端导入根证书否则连接失败。transactionCoordinatorEnabledtrue为什么开启事务支持。这是Pulsar 2.8新特性实现跨topic、跨分区的原子操作。电商下单扣库存场景必备。启动broker前务必检查ZK和BookKeeper状态# 检查ZK是否健康 echo stat | nc zk1.example.com 2181 | grep Mode # 检查BookKeeper是否注册 /opt/bookie/bin/bookkeeper shell listbookies -rw # 启动broker后台运行 bin/pulsar-daemon.sh start broker3.4 Pulsar Manager图形界面PostgreSQL驱动下的高可用部署Pulsar Manager的安装难点不在代码编译而在数据库适配和反向代理配置。官方Docker镜像apachepulsar/pulsar-manager:v0.3.0默认用H2我们必须替换成PostgreSQL。首先部署PostgreSQL 13.10# Ubuntu 20.04 apt-get install postgresql-13 postgresql-client-13 sudo -u postgres psql -c CREATE DATABASE pulsar_manager; sudo -u postgres psql -c CREATE USER pulsar WITH PASSWORD StrongPass123!; sudo -u postgres psql -c GRANT ALL PRIVILEGES ON DATABASE pulsar_manager TO pulsar;修改PostgreSQL配置/etc/postgresql/*/main/postgresql.conflisten_addresses 192.168.1.40 # Manager服务器IP port 5432 max_connections 500 shared_buffers 256MB/etc/postgresql/*/main/pg_hba.conf添加host pulsar_manager pulsar 192.168.1.0/24 md5重启PostgreSQLsystemctl restart postgresql下载并配置Pulsar Managerwget https://github.com/apache/pulsar-manager/releases/download/v0.3.0/apache-pulsar-manager.tar.gz tar -xzf apache-pulsar-manager.tar.gz cd pulsar-manager修改application.properties关键# 数据库配置替换默认H2 spring.datasource.driver-class-nameorg.postgresql.Driver spring.datasource.urljdbc:postgresql://192.168.1.40:5432/pulsar_manager?useSSLfalseserverTimezoneUTCallowPublicKeyRetrievaltrue spring.datasource.usernamepulsar spring.datasource.passwordStrongPass123! # Pulsar集群配置 pulsar-manager.cluster-namemy-pulsar-cluster pulsar-manager.broker-service-urlhttp://192.168.1.30:8080 pulsar-manager.admin-service-urlhttp://192.168.1.30:8080 # JWT认证若Pulsar开启了认证 pulsar-manager.jwt-tokeneyJhbGciOiJIUzI1NiJ9.xxxxx启动Manager./gradlew build -x test java -jar build/libs/pulsar-manager.jar --spring.config.locationapplication.properties此时Manager监听在http://localhost:9527但生产环境必须加Nginx反向代理实现HTTPS和负载均衡# /etc/nginx/sites-available/pulsar-manager server { listen 443 ssl; server_name pm.example.com; ssl_certificate /etc/letsencrypt/live/pm.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/pm.example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:9527; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }实操心得Pulsar Manager首次启动会自动初始化数据库表耗时约2-3分钟。此时访问页面会显示“Database initialization in progress...”。不要刷新等待即可。若超时检查PostgreSQL日志/var/log/postgresql/postgresql-*.log90%是密码错误或网络不通。4. 图形界面深度使用与集群健康诊断实战4.1 从“看不见”到“一眼定位”Pulsar Manager核心监控视图解析安装完Pulsar Manager只是起点真正价值在于它如何帮你把抽象的集群指标转化为可操作的决策。登录https://pm.example.com默认账号admin/admin首页的“Cluster Health”仪表盘是第一个必看区域。它不是简单罗列数字而是用颜色编码揭示风险等级绿色所有broker、bookie、ZK节点在线无延迟告警。黄色某个broker的msgRateIn超过阈值默认10000 msg/s或storageSize使用率85%提示需扩容。红色bookieDown数量0或zookeeperLatency平均100ms意味着集群已处于亚健康状态。点击任一broker进入详情页左侧导航栏的“Topics”标签页是高频使用区。这里能看到该broker托管的所有topic按Backlog未确认消息量排序一眼揪出积压大户。例如我们曾发现一个persistent://public/default/sensor-datatopic backlog高达2.3亿条点进去看“Subscriptions”子页发现其唯一的订阅sub-iot的unackedMessages为0但msgRateOut为0说明消费者彻底卡死。此时无需登录broker服务器查日志直接在Manager界面点击“Reset Cursor”按钮将游标重置到最早位置消费者重启后立即开始消费积压。“Brokers”总览页的“Load Report”功能更强大。它每30秒采集一次broker的CPU、内存、Direct Memory、连接数、topic数并生成热力图。当某broker内存使用率持续90%时热力图会标红点击该broker的“Load Report”链接可下钻查看过去1小时的内存增长曲线。我们据此发现一个规律每当directMemory使用率突破80%broker就会触发Full GC导致1-2秒的STWStop-The-World客户端报TimeoutException。解决方案是调大-XX:MaxDirectMemorySize8gJVM参数并在Manager中设置告警规则directMemoryUsage 75%时邮件通知。注意Manager的监控数据并非实时而是基于Pulsar内置的Metrics系统Prometheus格式拉取。默认采集间隔是30秒若需更高精度需修改conf/metrics.conf中的metricsProviderClassNameorg.apache.pulsar.broker.stats.prometheus.PrometheusMetricsProvider及metricsServletPath/metrics再配置Prometheus Server定时抓取。4.2 权限管理实战如何让开发只看到自己的租户Pulsar Manager默认是超级管理员视角所有租户、命名空间、topic一览无余。但生产环境必须做权限隔离。Pulsar原生支持RBAC基于角色的访问控制Manager将其可视化。首先进入“Settings” “Permissions”创建角色角色名dev-reader权限tenant:read,namespace:read,topic:read,subscription:read关联租户public然后创建用户用户名dev-team密码DevPass2024!角色dev-reader租户public此时dev-team登录后只能看到public租户下的资源且无法执行delete、create等写操作。更精细的控制在“Tenants”页面点击public租户右侧的“Edit”在“Allowed clusters”中只勾选my-pulsar-cluster这样即使未来接入新集群该租户也无法使用。我们曾用此功能解决一个棘手问题某客户有5个业务线共用一个Pulsar集群每个业务线有自己的topic前缀如iot-xxx、pay-xxx。我们为每个业务线创建独立租户iot、pay并在Manager中为他们的负责人分配tenant:owner角色。这样支付团队的负责人只能管理pay租户下的所有资源完全看不到IoT团队的topic审计日志也清晰记录谁在何时操作了哪个租户。4.3 故障排查速查5个典型问题的界面化诊断路径Pulsar Manager最大的价值是把原本需要SSH登录、翻日志、查命令的故障排查变成点几下鼠标的流程化操作。以下是5个高频问题的标准处理路径问题1客户端报Failed to get partitioned topic metadata诊断路径Manager “Brokers” 找到报错broker “Topics” 搜索报错topic名 查看“Partitions”列原因该topic分区数为0或broker未加载该topic元数据解决在“Topics”页点击topic名 “Actions” “Unload Topic”强制broker卸载并重新加载问题2消息消费延迟飙升msgBacklog持续增长诊断路径Manager “Topics” 按Backlog排序 点击高积压topic “Subscriptions” 查看unackedMessages和msgRateOut原因若unackedMessages 0且msgRateOut 0说明消费者卡死若unackedMessages 0但msgRateOut低说明消费者处理慢解决前者点击“Reset Cursor”后者在“Subscriptions”页点击“Skip Messages”跳过卡住的消息问题3Broker CPU持续100%诊断路径Manager “Brokers” 点击高CPU broker “Load Report” 查看“Direct Memory Usage”原因Direct Memory泄漏常见于Netty缓冲区未释放解决在broker配置中增加-XX:UseG1GC -XX:MaxGCPauseMillis20并重启broker问题4BookKeeper写入失败No available bookies诊断路径Manager “Clusters” “Bookies” 查看offline bookie列表 点击offline bookie IP “Logs”原因journal盘写满或ledger盘inode耗尽解决登录bookie服务器执行df -h /mnt/journal和df -i /mnt/ledger清理日志或扩容问题5Pulsar Manager页面加载缓慢或白屏诊断路径浏览器F12 Network 刷新页面 查看/api/v1/clusters等API请求的Response原因PostgreSQL连接池耗尽或ZK连接超时解决检查PostgreSQL的max_connections是否足够在Manager配置中增加spring.datasource.hikari.maximum-pool-size50实操心得我们给所有客户部署时都会在Manager中预置一套“健康检查”脚本。在“Settings” “Scripts”中创建一个Shell脚本内容为curl -s http://192.168.1.30:8080/admin/v2/brokers | jq . | length用于统计在线broker数。设置为每5分钟执行一次结果写入日志。这样当broker数突变为0时脚本能第一时间触发告警比等用户投诉快10分钟。5. 常见问题与独家避坑技巧实录5.1 ZooKeeper集群脑裂后的强制恢复指南脑裂Split-Brain是ZooKeeper最危险的状态集群分裂成两个独立的多数派各自选出leader导致数据不一致。现象是zkServer.sh status在不同节点返回Mode: leader且ZK客户端连接时断时续。绝对禁止直接重启所有节点这会导致元数据永久损坏。正确恢复步骤立即停止所有ZK写入在Pulsar broker配置中临时注释zookeeperServers重启broker使其离线。确定法定人数Quorum3节点集群法定人数是2。找出拥有最多最新数据的2个节点。方法比较/data/zk/version-2/目录下snapshot.*文件的修改时间取最新的两个。清空第三个节点的数据在疑似落后的节点上删除/data/zk/version-2/下所有文件保留myid。逐个重启先启两个“权威节点”等它们都显示Mode: follower后再启第三个节点。此时它会自动从leader同步数据。验证数据一致性用zkCli.sh连接任意节点执行ls /ledgers/available确认bookie列表一致。我们曾用此法在30分钟内恢复一个金融客户的ZK集群避免了数小时的业务中断。关键点是不猜、不试、只认数据文件时间戳。5.2 BookKeeper Ledger损坏的零丢失修复术BookKeeper的ledger损坏通常表现为broker日志出现LedgerOpenException或BookieHandleNotAvailableException。传统做法是bookkeeper shell ledgermetadata查损坏ledger再bookkeeper shell recover但恢复过程可能丢消息。我们的零丢失方案定位损坏ledger在broker日志中搜索Failed to open ledger提取ledger ID如12345。检查ledger状态/opt/bookie/bin/bookkeeper shell ledgermetadata -l 12345若显示State: IN_RECOVERY说明正在自动修复等待即可。若显示State: CLOSED但LastEntryId 0说明ledger为空可安全删除/opt/bookie/bin/bookkeeper shell deleteledger -l 12345若LastEntryId 0但Length 0说明数据丢失此时执行/opt/bookie/bin/bookkeeper shell recover -l 12345 -e 0 -f强制从其他副本恢复。避坑技巧BookKeeper的autorecovery功能默认开启但它的恢复线程数只有1。在大规模集群中我们将其调至autoRecoveryDaemonNumThreads8并设置underreplicatedLedgerCheckIntervalSeconds30确保损坏ledger在1分钟内被发现并修复。5.3 Pulsar Manager与JWT认证的深度集成当Pulsar开启JWT认证后Manager必须携带有效token才能调用Admin API。很多人卡在401 Unauthorized错误。根源在于token的audience受众声明必须匹配Pulsar配置的authenticationProviders。正确配置步骤在Pulsarconf/broker.conf中authenticationProvidersorg.apache.pulsar.broker.authentication.AuthenticationProviderToken tokenPublicKey/path/to/public.key生成token时audience必须是pulsarPulsar默认值# 使用jwt-cli工具 jwt encode --secret-file private.key --audience pulsar --iss pulsar-admin将生成的token粘贴到Manager的application.properties中pulsar-manager.jwt-tokeneyJhbGciOiJIUzI1NiJ9.xxxxx若token audience不匹配Manager会静默失败页面无提示。此时需查看Manager日志logs/pulsar-manager.log搜索401确认错误详情。5.4 Windows Subsystem for Linux (WSL) 下的Pulsar开发环境搭建很多开发者想在Windows 10上本地调试Pulsar集群但WSL2的网络模型与Linux原生不同。直接在WSL中启动standalone会遇到brokerServiceUrl无法被Windows主机访问的问题。解决方案是利用WSL2的localhost穿透在WSL中启动Pulsarbin/pulsar standalone -nss -nss -nss修改conf/standalone.confadvertisedAddress0.0.0.0 brokerServicePort6650 webServicePort8080在Windows主机上用http://localhost:8080访问Manager但需在WSL中启动Manager时指定java -jar pulsar-manager.jar --spring.config.locationapplication.properties --server.address0.0.0.0 --server.port9527最关键一步在Windows PowerShell中执行netsh interface portproxy add v4tov4 listenport9527 listenaddress127.0.0.1 connectport9527 connectaddress$(wsl hostname -I)这样Windows的http://localhost:9527就能穿透到WSL的Manager服务。我们实测此方案在WSL2 Ubuntu 22.04上100%可用解决了90%的Windows开发者本地调试难题。5.5 生产环境必须做的5项加固措施ZooKeeper ACL加固默认ZK是开放的任何客户端都能读写。执行echo addauth digest admin:123456 | /opt/zookeeper/bin/zkCli.sh -server zk1:2181 echo setAcl / digest:admin:123456: