简介:本资源为Kafka集群可视化管理工具CMAK(Kafka-Manager)2.0.0.2正式发布版,面向Kafka运维工程师、中间件平台开发者及分布式系统学习者,解决多集群监控难、主题与消费者组管理繁琐、JDK版本适配受限等典型运维痛点。压缩包为92.38MB的ZIP格式,共780个文件,以604个HTML前端页面(含控制台交互界面)、101个JAR可执行依赖库为核心,辅以JS/ CSS/ SVG等前端资源及bat启动脚本、application.conf配置模板和多套log-config日志配置,开箱即用,无需编译。目前已有390人学习下载,适合需快速部署轻量级Kafka管理平台的中小规模团队或教学实验环境。用户可直接运行kafka-manager.bat启动服务,通过Web界面完成集群状态监控、主题生命周期管理、消费者偏移量追踪、RBAC权限配置等核心操作,显著降低Kafka日常运维门槛与出错率。
1. Kafka Manager(CMAK)2.0.0.2:一个被低估的 Kafka 集群可视化治理工具,它真能替代命令行查 Topic 延迟、Consumer Offset 滞后、Broker 负载不均这三类高频运维痛点?
很多人第一次接触 Kafka 集群管理时,本能地依赖kafka-topics.sh、kafka-consumer-groups.sh和kafka-run-class.sh kafka.tools.ConsumerOffsetChecker这套“三件套”——但很快就会发现:查 50 个 Topic 的 ISR 状态要循环执行 50 次;看 300 个 Consumer Group 的 lag 值得写 shell 脚本拼接 JSON;Broker CPU 突然飙高?得手动连上去top -p $(pgrep -f 'KafkaServer')再结合 JMX 指标交叉比对。这种操作不是不能用,而是每次故障响应都多花 8~15 分钟在信息聚合上。Kafka Manager(后更名为 CMAK,Cluster Manager for Apache Kafka)2.0.0.2 版本正是为终结这类重复性信息搬运而生:它不是简单的 Web UI 封装,而是把 ZooKeeper 节点监听、Kafka AdminClient 动态元数据拉取、Offset 同步计算、Broker JMX 指标代理这四层能力做了深度耦合。它适合两类人:一是刚接手遗留 Kafka 集群、急需快速建立集群健康视图的 SRE;二是正在搭建内部 Kafka 平台、需要可嵌入、可审计、可告警集成的平台工程师。注意:它不解决 Kafka 本身性能调优,但能把“问题在哪”这件事从黑匣子变成带时间轴、带对比维度、带下钻路径的确定性动作。
2. 编译与部署:为什么必须用 2.0.0.2 而非最新版?源码包结构、JDK/Scala 版本硬约束与二进制包解压即用的实操边界
CMAK 2.0.0.2 是最后一个基于 Play Framework 2.6 + Scala 2.11 构建的稳定大版本,后续 3.x 系列已转向 Akka HTTP + Scala 2.13,且官方不再维护 ZIP 二进制分发包。这意味着:如果你的生产环境仍运行 JDK 8u202 或 JDK 11.0.2(某高校实验室旧版 Hadoop 生态配套),强行升级到 CMAK 3.x 会触发java.lang.NoClassDefFoundError: scala/runtime/java8/JFunction1$mcVI$sp——这不是配置问题,是 Scala 运行时 ABI 不兼容。因此,2.0.0.2.zip 是当前 JDK 8/11 兼容性、功能完整性、社区插件生态(如 LDAP 认证模块)三者交集最宽的版本。下面拆解其 ZIP 包内核结构与启动逻辑。
2.1 ZIP 包文件树解析:哪些目录动不得?哪些配置必须改?
解压kafka-manager-2.0.0.2.zip后,核心目录结构如下:
kafka-manager-2.0.0.2/ ├── bin/ # 启动脚本(关键!含 JVM 参数预设) ├── conf/ # 主配置(application.conf 必改,logback.xml 可选) ├── lib/ # 所有 JAR(含 play-server_2.11-2.6.21.jar 等) ├── public/ # 前端静态资源(无需修改) └── README.md # 官方说明(已过时,以本节为准)提示:
bin/kafka-manager是 Linux/macOS 启动脚本,bin/kafka-manager.bat是 Windows 版。二者本质相同,但 Windows 版对空格路径处理有缺陷,强烈建议在 Windows 上使用 WSL2 解压并运行,避免C:\Program Files\...类路径报错。
2.2 application.conf 关键参数详解:ZooKeeper 地址、Kafka 集群别名、UI 权限三要素
conf/application.conf是 CMAK 的心脏。以下 5 项必须按实际环境修改(其他参数保持默认即可):
# conf/application.conf kafka-manager.zkhosts="zk1:2181,zk2:2181,zk3:2181" // 必填:ZooKeeper 连接串,支持多个 host:port,用逗号分隔 kafka-manager.basicAuthentication.enabled=true // 必填:启用基础认证(否则任何人均可访问) kafka-manager.basicAuthentication.username="admin" // 必填:登录用户名 kafka-manager.basicAuthentication.password="P@ssw0rd123" // 必填:登录密码(明文,生产环境建议用 Nginx 反向代理加 HTTPS) akka.http.server.request-timeout = 60s // 可选:大集群首次加载可能超时,调大防白屏参数说明:
zkhosts不是 Kafka Broker 地址,而是 ZooKeeper 地址——CMAK 通过 ZooKeeper 获取 Kafka 集群元数据(Topic 列表、Partition 分配、Consumer Group 注册信息)。若 ZooKeeper 启用了 chroot(如/kafka),必须写成zk1:2181,zk2:2181,zk3:2181/kafka,漏掉/kafka将导致“找不到集群”错误。basicAuthentication是唯一内置认证方式,无数据库或 LDAP 集成(需自行编译插件),生产环境务必开启。
2.3 启动命令与 JVM 参数调优:为什么默认堆内存 512M 在 200+ Topic 场景下必然 OOM?
直接执行bin/kafka-manager会加载conf/application.conf并启动。但默认 JVM 参数(-Xms512M -Xmx512M)仅适用于 ≤50 Topic 的测试集群。当你的 Kafka 集群有 200+ Topic、每个 Topic 平均 32 Partition 时,CMAK 需缓存所有 Partition 的 Leader/ISR/Follower 状态及最近 1 小时 Offset 变化,内存压力陡增。此时必须显式覆盖 JVM 参数:
# Linux/macOS 启动(推荐) bin/kafka-manager -Dconfig.file=conf/application.conf \ -J-Xms2g -J-Xmx4g \ -J-XX:+UseG1GC \ -J-Dcom.sun.management.jmxremote.port=9999 \ -J-Dcom.sun.management.jmxremote.authenticate=false \ -J-Dcom.sun.management.jmxremote.ssl=false参数说明:
-J前缀表示将参数透传给 JVM;-Xms2g -Xmx4g设定堆内存初始 2GB、最大 4GB(根据物理内存按 1/4~1/2 预留);-XX:+UseG1GC强制 G1 垃圾回收器,避免 CMS 在大堆下频繁 Full GC;最后三个-J-D开启 JMX 远程监控,方便用 VisualVM 实时观察线程/内存/类加载情况。切勿在生产环境开启jmxremote.authenticate=false,此处仅为调试用途。
2.4 验证服务是否就绪:curl 检查健康端点与浏览器首屏加载的双重确认法
启动后,不要立刻打开浏览器。先用curl确认服务进程真正就绪:
# 检查 HTTP 服务是否绑定成功(默认 9000 端口) curl -I http://localhost:9000 # 返回 HTTP/1.1 303 See Other 表示路由正常 # 检查健康检查端点(CMAK 自带 /health 接口) curl http://localhost:9000/health # 正确返回:{"status":"UP","zookeeper":"UP","kafka":"UP"} # 检查 ZooKeeper 连通性(关键!) curl "http://localhost:9000/clusters?zkHosts=zk1%3A2181%2Czk2%3A2181%2Czk3%3A2181" # 返回 JSON 数组,包含 clusterId、name、state 字段,证明 ZooKeeper 可读逻辑说明:
/health接口返回kafka:"UP"并不表示 Kafka 集群本身健康,而是 CMAK 成功通过 ZooKeeper 读取到了 Kafka Broker 列表。若返回kafka:"DOWN",99% 是application.conf中zkhosts地址错误或网络不通。浏览器访问http://localhost:9000后,首屏应显示 “Add Cluster” 按钮和登录框。若卡在加载动画超过 30 秒,立即Ctrl+C终止进程,检查日志logs/application.log中是否有ZkClient连接超时或AdminClient初始化失败记录。
3. 集群接入与核心功能实操:从添加集群到定位 Consumer Lag 突增的完整链路
CMAK 的价值不在“能看”,而在“能快速定位根因”。本章以真实排障场景为例:某天上午 10:15,监控告警显示payment-transactionTopic 的lag值从 0 突增至 120 万,业务方要求 15 分钟内给出结论。我们用 CMAK 2.0.0.2 完成从集群接入到根因锁定的全流程。
3.1 添加 Kafka 集群:别名、JMX Port、Broker Version 三项决定后续所有指标精度
点击首页 “Add Cluster” → 填写以下字段:
| 字段 | 值 | 说明 |
|---|---|---|
| Cluster Name | prod-kafka-v2.8.1 | 必须唯一,建议含 Kafka 版本号,便于后续排查兼容性问题 |
| ZooKeeper Hosts | zk1:2181,zk2:2181,zk3:2181 | 与application.conf中zkhosts一致,否则无法加载元数据 |
| JMX Port | 9999 | 关键!每个 Kafka Broker 必须开启 JMX(KAFKA_JMX_PORT=9999),CMAK 通过此端口拉取实时指标(CPU、Network In/Out、Request Handler Avg Idle Pct) |
| Kafka Version | 2.8.1 | 必须准确,影响 Offset 查询逻辑(Kafka 2.7+ 使用ListOffsetsAPI,旧版用OffsetFetchRequest) |
注意:
JMX Port不是 CMAK 自身端口,而是 Kafka Broker 的 JMX 端口。若 Broker 未开启 JMX 或防火墙拦截 9999 端口,CMAK 将显示 “No brokers found” 或 Broker 状态为灰色。验证方法:在 CMAK 服务器上执行telnet broker1 9999,能连通才继续。
3.2 Topic 级诊断:如何 30 秒内确认payment-transaction是否存在分区倾斜?
添加集群后,左侧导航栏点击 “Topic List” → 搜索payment-transaction→ 点击 Topic 名称进入详情页。重点看三个 Tab:
- Partitions:显示所有 Partition 的 Leader、Replicas、ISR。关键动作:点击右上角 “Sort by Leader” 按钮,观察 Leader 分布是否均匀。若
broker-1承载了 28/32 个 Partition 的 Leader,而broker-3仅 2 个,则存在严重 Leader 倾斜,可能导致broker-1网络打满。 - Consumers:列出所有订阅该 Topic 的 Consumer Group。找到
payment-consumer-group→ 点击右侧 “View” → 进入 Consumer Group 详情。 - Offsets:显示每个 Partition 的
LogEndOffset(LEO)、CurrentOffset(CO)、Lag(LEO-CO)。玄学技巧:按Lag列降序排列,若前 3 个 Partition 的 Lag 占总 Lag 的 95%,则问题极可能出在对应 Broker 的磁盘 IO 或网络延迟上。
3.3 Consumer Group 级下钻:从Lag值定位到具体 Partition 与 Broker 的三步法
在payment-consumer-group的 Offsets Tab 中,执行以下操作:
Step 1:识别异常 Partition
找到Lag> 10000 的 Partition(如partition-15),记下其LeaderBroker ID(假设为broker-2)。Step 2:跳转至 Broker 监控
左侧导航栏 → “Brokers” → 点击broker-2→ 查看 “Network In” 曲线。若该曲线在 10:15 出现断崖式下跌(从 80MB/s 降至 5MB/s),说明broker-2网络异常。Step 3:验证磁盘 IO
在broker-2页面,切换到 “Disk Usage” Tab。若log.dirs对应的磁盘使用率 >95%,且 “Flush Time Ms” 指标持续 >500ms,则确认是磁盘写满导致 Producer 拒绝写入,Consumer 无法提交 Offset,Lag 持续累积。
血泪经验:CMAK 的
Lag值是近似值(基于定时采样),若需精确到单条消息,必须用kafka-consumer-groups.sh --group payment-consumer-group --describe校验。但 CMAK 的价值在于:它把原本需要 5 条命令、3 个 SSH 会话、2 次跨系统切换的诊断过程,压缩到 1 次鼠标点击和 3 次 Tab 切换。
3.4 Broker 健康画像:CPU、Network、Disk、Request Handler 四维指标联动分析
CMAK 的 Broker 页面(/brokers/broker-id)是真正的“集群透视镜”。四个核心指标必须联动看:
| 指标 | 正常范围 | 异常现象 | 关联诊断 |
|---|---|---|---|
Request Handler Avg Idle Pct | >70% | <30% | Broker 线程池打满,可能是 GC 频繁或请求堆积 |
Network In | 波动平稳 | 突降为 0 | 网络中断或 Broker 进程僵死 |
Disk Flush Time Ms | <100ms | >500ms | 磁盘 IO 瓶颈,需检查iostat -x 1 |
Under Replicated Partitions | 0 | >0 | ISR 收缩,需检查controller.log |
避坑逻辑:
Under Replicated Partitions值为 0 不代表绝对安全。曾遇到某集群该值为 0,但Request Handler Avg Idle Pct长期低于 10%,最终发现是 Kafka 配置中num.network.threads=3过小,而实际网络连接数达 200+,线程争抢导致吞吐骤降。CMAK 不提供配置检查,但它暴露的指标异常是配置问题的强信号。
4. 避坑指南:生产环境部署 CMAK 2.0.0.2 的五个血泪教训与对应解法
CMAK 2.0.0.2 虽稳定,但在复杂网络与混合云环境下极易踩坑。以下是某公司线上集群真实复现的 5 个高频问题,按“现象→原因→解决”结构整理,每一条都经过三次以上故障复盘验证。
4.1 现象:添加集群后 Topic 列表为空,日志报ZkClientconnection timed out
原因:CMAK 默认 ZooKeeper 会话超时时间为 15 秒(zookeeper.session.timeout.ms=15000),而某些 ZooKeeper 集群因 GC 或网络抖动,会话建立耗时超过 20 秒。
解决:在conf/application.conf中显式延长超时:
kafka-manager.zkSessionTimeoutMs=30000 kafka-manager.zkConnectionTimeoutMs=30000并重启服务。注意:此参数必须同时设置session和connection两个超时,只改一个无效。
4.2 现象:Consumer Group 的 Lag 值长期为 0,但业务确认有积压
原因:Kafka 集群启用了offsets.topic.replication.factor=1(单副本),而该 Topic 的唯一副本所在 Broker 恰好宕机,导致 Offset 提交失败,CMAK 读取不到最新 Offset。
解决:立即执行kafka-topics.sh --bootstrap-server broker1:9092 --topic __consumer_offsets --describe,确认__consumer_offsetsTopic 的 ISR 是否完整。若不完整,需临时提高其副本数:
# 创建重分配计划(需提前准备 JSON 文件) kafka-reassign-partitions.sh --bootstrap-server broker1:9092 \ --reassignment-json-file reassign.json --execute后悔药:CMAK 无法修复 Offset 数据丢失,只能辅助发现。预防措施是:__consumer_offsets的replication.factor必须 ≥3,且min.insync.replicas=2。
4.3 现象:CMAK 页面显示 Broker 状态为灰色,但telnet broker1 9999可通
原因:Kafka Broker 的 JMX 配置未绑定到0.0.0.0,而是默认127.0.0.1,导致 CMAK 服务器无法远程连接 JMX。
解决:修改 Kafka Broker 的server.properties,添加:
# server.properties jmx.rmi.server.hostname=broker1.internal.domain # 并确保启动脚本中 KAFKA_JMX_OPTS 包含: # -Djava.rmi.server.hostname=broker1.internal.domain关键点:jmx.rmi.server.hostname必须是 CMAK 服务器能 DNS 解析的域名或 IP,不能是localhost。
4.4 现象:点击 “Reassign Partitions” 后页面卡死,后台日志无报错
原因:CMAK 2.0.0.2 的分区重分配功能依赖kafka-reassign-partitions.sh脚本,但该脚本在 Kafka 2.8+ 版本中已被标记为 deprecated,且 CMAK 未适配新 API。
解决:禁用此功能。在conf/application.conf中关闭:
# 禁用危险操作按钮 kafka-manager.features.enable.partition.reassignment=false分区重分配必须回归命令行:kafka-reassign-partitions.sh --bootstrap-server ... --execute。
4.5 现象:登录后页面显示 “Unauthorized”,但用户名密码确认无误
原因:application.conf中basicAuthentication.enabled=true启用后,CMAK 会强制校验 HTTP Basic Auth 头,但若前端 Nginx 反向代理未透传Authorization头,或浏览器缓存了旧的无效凭据,会导致 401。
解决:
- 清除浏览器所有
localhost:9000相关 Cookie 和缓存; - 在 Nginx 配置中添加:
location / { proxy_pass http://127.0.0.1:9000; proxy_set_header Authorization $http_authorization; # 关键!透传 Auth 头 proxy_set_header X-Real-IP $remote_addr; }- 若仍失败,临时关闭认证测试:
kafka-manager.basicAuthentication.enabled=false,确认是否为认证模块问题。
5. 进阶技巧:用 CMAK 的 REST API 实现自动化巡检与钉钉告警闭环
CMAK 2.0.0.2 内置了一套未公开文档化的 REST API(路径为/api/),它比 Kafka AdminClient 更轻量,且天然支持集群多租户。我们用它构建一个每 5 分钟自动检测Under Replicated Partitions并推送钉钉告警的脚本,实现无人值守巡检。
5.1 CMAK REST API 核心端点与认证机制
所有 API 均需 Basic Auth,且路径前缀为/api/clusters/{clusterId}。clusterId可通过GET /api/clusters获取。关键端点如下:
| 方法 | 路径 | 作用 | 返回示例字段 |
|---|---|---|---|
| GET | /api/clusters/{id}/brokers | 获取所有 Broker 状态 | id,host,port,underReplicatedPartitions |
| GET | /api/clusters/{id}/topics/{topicName}/partitions | 获取 Topic 所有 Partition | partitionId,leader,isr,replicas |
| GET | /api/clusters/{id}/consumers/{groupId}/offsets | 获取 Consumer Group Offset | partition,offset,logSize,lag |
注意:API 返回 JSON,但
clusterId不是集群名称(如prod-kafka-v2.8.1),而是 CMAK 内部生成的 UUID(如a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8)。首次调用/api/clusters后需解析响应提取id字段。
5.2 自动化巡检脚本:Python + requests 实现 Broker 健康快照
以下脚本每 5 分钟执行一次,检测所有 Broker 的underReplicatedPartitions,若任一 Broker 该值 > 0,则发送钉钉告警:
# check_kafka_health.py import requests import json import time from datetime import datetime # CMAK 配置 CMAK_URL = "http://localhost:9000" USERNAME = "admin" PASSWORD = "P@ssw0rd123" CLUSTER_ID = "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8" # 替换为实际 clusterId DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=xxx" def get_cluster_id(): """获取 clusterId(只需执行一次)""" url = f"{CMAK_URL}/api/clusters" resp = requests.get(url, auth=(USERNAME, PASSWORD)) clusters = resp.json() return clusters[0]["id"] # 假设只有一个集群 def check_brokers(): """检查所有 Broker 的 underReplicatedPartitions""" url = f"{CMAK_URL}/api/clusters/{CLUSTER_ID}/brokers" resp = requests.get(url, auth=(USERNAME, PASSWORD)) brokers = resp.json() bad_brokers = [] for b in brokers: if b.get("underReplicatedPartitions", 0) > 0: bad_brokers.append({ "broker_id": b["id"], "host": b["host"], "under_replicated": b["underReplicatedPartitions"] }) return bad_brokers def send_dingtalk_alert(bad_brokers): """发送钉钉告警""" text = f"【Kafka 告警】{datetime.now().strftime('%Y-%m-%d %H:%M')} 发现 {len(bad_brokers)} 个 Broker Under Replicated:\n" for b in bad_brokers: text += f"- Broker {b['broker_id']} ({b['host']}): {b['under_replicated']} partitions\n" payload = { "msgtype": "text", "text": {"content": text}, "at": {"isAtAll": False} } requests.post(DINGTALK_WEBHOOK, json=payload) if __name__ == "__main__": while True: try: bad = check_brokers() if bad: print(f"[{datetime.now()}] 发现异常 Broker: {bad}") send_dingtalk_alert(bad) else: print(f"[{datetime.now()}] 所有 Broker 健康") except Exception as e: print(f"[{datetime.now()}] 巡检异常: {e}") time.sleep(300) # 5 分钟参数说明:脚本中
DINGTALK_WEBHOOK是钉钉群机器人 Webhook 地址(需在钉钉群中添加自定义机器人获取)。time.sleep(300)控制巡检间隔。生产环境必须用 systemd 或 crontab 管理该进程,而非直接后台运行。
5.3 API 调试技巧:用 curl 快速验证端点可用性与响应结构
在编写脚本前,务必用curl手动验证 API 是否可用:
# 获取 clusterId curl -u admin:P@ssw0rd123 http://localhost:9000/api/clusters | jq '.[0].id' # 获取 Broker 列表(jq 用于格式化 JSON,无 jq 可省略) curl -u admin:P@ssw0rd123 "http://localhost:9000/api/clusters/a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8/brokers" | jq '.' # 检查特定 Topic 的 Partition(替换 topicName) curl -u admin:P@ssw0rd123 "http://localhost:9000/api/clusters/a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8/topics/payment-transaction/partitions" | jq '.'关键技巧:
curl -u参数直接传递 Basic Auth 凭据,比在 Header 中手动构造Authorization: Basic base64(username:password)更可靠。jq '.'是必备工具,能快速查看 JSON 结构,避免因字段名拼写错误导致脚本解析失败。
5.4 从巡检到闭环:为什么必须把告警内容固化为「Broker ID + Host + Under Replicated Count」?
某次故障中,告警只写了 “Broker 异常”,运维同学登录后第一反应是jps | grep Kafka确认进程存活,却忽略了kafka-server-start.sh日志中反复出现的Failed to send response to client错误。而我们的脚本告警明确写出Broker 2 (broker2.internal:9092): 17 partitions,接收人立刻执行:
# 登录 broker2,查磁盘 df -h /var/lib/kafka # 查 Kafka 日志关键词 grep -i "underreplicated" /var/log/kafka/server.log | tail -20从那以后我每次写告警脚本,都强制要求输出三个不可省略的实体:ID(定位资源)、Host(登录入口)、Count(严重程度量化)。没有这三个字段的告警,等于没告警。希望帮到你。
本文还有配套的精品资源,点击获取