v1.9 带来 12 个新场景 - dr 模块再添十个,新的 tiered-storage 模块两个 - 并让 Kafka Simulator 的课程体系达到 134 个中的 112 个。它还公开了模拟器从一开始就依赖的一样东西:它的链接格式。

v1.9 里有什么

更多灾难恢复(dr,10 个场景)。 两种平台层面的答案,回应 v1.8 借 MirrorMaker 2 提出的那些问题:

分层存储(tiered-storage,2 个场景)。 旧的日志段被卸载到对象存储:卸载、读回和过期的完整生命周期,伴随着 localStartOffset 与 logStartOffset 逐渐分开 - 以及无限保留:老化的日志段离开本地磁盘,但一个滞后的消费者仍会把它们逐一读回来。

每个会话都是一个链接

演练场把它的全部状态都保存在 URL 里。一个链接可以在指定步骤打开一个脚本化场景、重放一串集群操作,或者搭起一个自定义的自由模式集群 - 模拟器里每一个「分享」按钮正是这样工作的。

从 v1.9 开始,这套格式公开并有文档记录(英文):查询参数、动作日志的语法、集群形态的编码,以及演练场如何处理它无法解析的条目。规范中的每个示例都会被模拟器自己的测试套件解码,因此文档不可能与代码脱节。

有文档的格式意味着链接可以来自演练场之外的地方 - 一个脚本、一个 CI 任务,或者一个 AI 代理。第一个生成器随本次发布一同推出。

monedula-sim-link:把真实集群变成一个链接

手动描述你真正关心的集群 - 一个个 broker、一个个主题地写 - 既繁琐又容易出错。monedula-sim-link 是一个小巧的 Go CLI,它以只读方式连接到真实的 Kafka 集群,并打印出将其可视化的演练场链接:

$ go install github.com/monedula-dev/monedula-sim-link/cmd/monedula-sim-link@latest
$ monedula-sim-link connect --brokers localhost:9092 --topics orders,payments
https://monedula.dev/kafka-simulator/playground?scenario=free&actions=…&size=…

这个链接会把运行中的集群作为一个模拟器打开:broker、主题、分区分布、副本因子、离线的 broker、ISR 缺口、带成员信息的消费者组、主题配置,以及数据量的抽样 - 一幅你可以暂停、单步执行、在不触碰生产环境的情况下搞坏的画面,还可以在事故处理中途把它发给同事,而不必写一段文字去描述。

只读,并且在一个文件里就能审计。 把一个工具指向生产集群是一个信任决定,所以这项保证范围窄且明确。connect 只发出读取请求 - ApiVersions、Metadata、ListOffsets,以及针对消费者组和配置的 ListGroups、DescribeGroups、OffsetFetch 和 DescribeConfigs。Metadata 请求会设置 AllowAutoTopicCreation=false,因此即使只是查找一个主题,也永远不会创建它。整个过程不生产任何记录、不修改任何配置、不加入任何消费者组,也不提交任何 offset。整个客户端接触面都在一个文件里,即 snapshot/kafka.go,并配有测试,证明一次失败的查找不会自动创建该主题,而读取一个消费者组的 offset 也永远不会改变它们。

适配集群的安全配置方式。 支持 TLS、双向 TLS 和 SASL/SCRAM,密码从 MONEDULA_SIM_LINK_PASSWORD 读取,因此不会留在 shell 历史中:

export MONEDULA_SIM_LINK_PASSWORD='…'
monedula-sim-link connect --brokers broker1:9093,broker2:9093 \
  --tls --ca-cert ./cluster-ca.pem \
  --sasl-mechanism scram-sha-512 --username viewer

主题可以按精确名称、按正则表达式或两者结合来选择,而 --dry-run 会在把 URL 交给你之前,打印真实名称到模拟器名称的映射,以及推导出的集群规模。链接所编码的一切,只是对形态的紧凑描述和数据量的抽样;模拟器没有后端,因此你的数据永远不会离开你的机器。

面向 AI 代理的 MCP 服务器

monedula-sim-link mcp 通过 stdio 使用 Model Context Protocol 通信,因此 Claude Code、Claude Desktop 或任何其他 MCP 客户端都能按需构建链接。你可以说「给我看一个 6 broker 的集群,其中 orders 的 leader 挂掉」或者「把我们的 staging 集群可视化」,代理就会返回一个恰好打开这些内容的链接。它提供四个工具:

  • build_playground_url - 根据声明式描述生成一个自由模式会话:一个拓扑、一个集群形态(broker;带有分区数、RF、min.insync.replicas 和清理策略的主题;机架感知),以及一个有序的定时动作列表 - 生产记录、杀掉并重启 broker、添加生产者和消费者组、配置变更、重分配、分层存储卸载、限流。
  • open_scenario - 按带点号的 ID(例如 00.1.3)给出某个精选脚本化场景的链接。
  • validate_actions - 对于一个原始的 actions 字符串或一个完整 URL,演练场实际会加载什么:保留下来的动作、每个被丢弃的条目及其原因,以及长度和数量相对于编解码器上限的情况。
  • cluster_to_url - 以工具形式提供的 connect 快照,带有同样的只读保证。

把 URL 的构建交给 LLM,正是事情会悄无声息地出错的地方 - 一个被弄乱的分隔符、一个模拟器不接受的配置路径、一个超出长度上限的 actions 值 - 而演练场会悄悄丢弃它无法解析的内容。所以每个工具都和 CLI 一样经过同一个快速失败的编解码器,只有当 URL 的 actions 值能解码回完全相同的日志时,才会返回这个 URL。校验失败时,错误信息会指明出问题的字段、分隔符或配置路径,这样代理就能修正自己的输入,而不是交出一个被截断的链接。

在 Claude Code 中注册它只需一行:

claude mcp add monedula-sim-link -- monedula-sim-link mcp

对于 Claude Desktop,把它添加到 claude_desktop_config.json 中:

{
  "mcpServers": {
    "monedula-sim-link": {
      "command": "monedula-sim-link",
      "args": ["mcp", "--base-url", "https://monedula.dev/kafka-simulator/playground"]
    }
  }
}

--base-url 是可选的;把它指向 http://localhost:4321/kafka-simulator/playground,就能生成指向本地开发服务器的链接。这个服务器基于官方的 modelcontextprotocol/go-sdk 构建。

monedula-sim-link 位于它自己的开源仓库中,即 GitHub 上的 monedula-dev/monedula-sim-link - 一个采用 Apache-2.0 许可证的自包含 Go 模块,可以用 go install 安装,也可以从发布页面获取适用于 Linux、macOS 和 Windows 的预编译二进制文件。它不发送任何遥测数据,并且是这套 URL 格式的参考生成器:它生成的链接在演练场中解码后,恰好就是它写入的那份日志。

像 Kafka 那样扩缩集群

自由模式现在会像真实集群那样改变 broker 数量。在 v1.9 之前,添加一个 broker 会悄悄地把分区再均衡到它上面 - 正如一位读者指出的,这并不是 Kafka 的做法。现在你添加的 broker 加入时是空的:不会有任何分区自行迁移到它上面,集群检查器也会说明这一点,旁边还有一个 Rebalance partitions 按钮。在终端中,kafka-reassign-partitions --generate 会根据主题列表和 broker 列表提出一个方案,--execute 启动它,--verify 确认它。反方向也遵循同样的规则:仍持有分区的 broker 必须先被排空,才能被移除,顺序与你下线一个真实 broker 时相同。

打开模拟器,用 Cluster Linking 对一个区域执行故障切换,然后分享链接。