---
title: "Kafka Simulator v1.9 - 平台层与公开的 URL 格式"
date: 2026-10-09T00:00:00.000Z
author: "michal"
excerpt: "Multi-Region Cluster 的 observer、Cluster Linking 和分层存储，用十二个场景补全了灾备与存储这条线 - 演练场的 URL 格式也正式公开，并配有 monedula-sim-link，把运行中的集群或 AI 代理给出的描述变成一个链接。"
---
v1.9 带来 **12 个新场景** - dr 模块再添十个，新的 tiered-storage 模块两个 - 并让 [Kafka Simulator](/kafka-simulator/) 的课程体系达到 **134 个中的 112 个**。它还公开了模拟器从一开始就依赖的一样东西：它的链接格式。

## v1.9 里有什么

**更多灾难恢复（`dr`，10 个场景）。** 两种平台层面的答案，回应 v1.8 借 MirrorMaker 2 提出的那些问题：

- **[Multi-Region Cluster 的 observer](/kafka-simulator/scenarios/mrc-observers/)** - 跟随日志、但不加入 ISR 的副本，因此一份远端副本不会给写入路径带来任何代价。[它们滞后多远](/kafka-simulator/scenarios/observer-lag/)、[该放在哪里](/kafka-simulator/scenarios/durability-vs-latency/)、[如何被提升](/kafka-simulator/scenarios/observer-promotion/) - 包括这样一种情况：[提升需要一个已经无法联系到的 leader](/kafka-simulator/scenarios/observer-promotion-reachable-leader/)。
- **[Cluster Linking](/kafka-simulator/scenarios/cluster-linking-offset-preserving/)** - 逐字节的镜像，保留 offset，因此完成故障切换的消费者无需任何转换。[镜像主题在被提升之前一直是只读的](/kafka-simulator/scenarios/mirror-read-only-promote-writable/)，[已提交的消费者 offset 会原样经由链路同步](/kafka-simulator/scenarios/consumer-offset-sync-link/)，[链路可以原地反转以实现干净的回切](/kafka-simulator/scenarios/bidirectional-links-failback/)，[还有一个场景在同一拓扑上把它与 MirrorMaker 2 并排运行](/kafka-simulator/scenarios/cluster-linking-vs-mm2/)。自由模式也获得了相应的控件：双区域拓扑上的区域与镜像链路编辑器，其中每条链路可以是 MirrorMaker 2 或 Cluster Linking，并且可以反转。

**分层存储（`tiered-storage`，2 个场景）。** 旧的日志段被卸载到对象存储：[卸载、读回和过期的完整生命周期](/kafka-simulator/scenarios/confluent-tiered-lifecycle/)，伴随着 `localStartOffset` 与 `logStartOffset` 逐渐分开 - 以及[无限保留](/kafka-simulator/scenarios/infinite-retention-tiered/)：老化的日志段离开本地磁盘，但一个滞后的消费者仍会把它们逐一读回来。

## 每个会话都是一个链接

演练场把它的全部状态都保存在 URL 里。一个链接可以在指定步骤打开一个脚本化场景、重放一串集群操作，或者搭起一个自定义的自由模式集群 - 模拟器里每一个「分享」按钮正是这样工作的。

从 v1.9 开始，这套格式[公开并有文档记录](/flock/docs/kafka-simulator/reference/url-format/)（英文）：查询参数、动作日志的语法、集群形态的编码，以及演练场如何处理它无法解析的条目。规范中的每个示例都会被模拟器自己的测试套件解码，因此文档不可能与代码脱节。

有文档的格式意味着链接可以来自演练场之外的地方 - 一个脚本、一个 CI 任务，或者一个 AI 代理。第一个生成器随本次发布一同推出。

## monedula-sim-link：把真实集群变成一个链接

手动描述你真正关心的集群 - 一个个 broker、一个个主题地写 - 既繁琐又容易出错。[monedula-sim-link](/zh/flock/sim-link/) 是一个小巧的 Go CLI，它以**只读**方式连接到真实的 Kafka 集群，并打印出将其可视化的演练场链接：

```bash
$ 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`](https://github.com/monedula-dev/monedula-sim-link/blob/main/snapshot/kafka.go)，并配有测试，证明一次失败的查找不会自动创建该主题，而读取一个消费者组的 offset 也永远不会改变它们。

**适配集群的安全配置方式。** 支持 TLS、双向 TLS 和 SASL/SCRAM，密码从 `MONEDULA_SIM_LINK_PASSWORD` 读取，因此不会留在 shell 历史中：

```bash
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 中注册它只需一行：

```bash
claude mcp add monedula-sim-link -- monedula-sim-link mcp
```

对于 Claude Desktop，把它添加到 `claude_desktop_config.json` 中：

```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`](https://github.com/modelcontextprotocol/go-sdk) 构建。

monedula-sim-link 位于它自己的开源仓库中，即 GitHub 上的 [monedula-dev/monedula-sim-link](https://github.com/monedula-dev/monedula-sim-link) - 一个采用 Apache-2.0 许可证的自包含 Go 模块，可以用 `go install` 安装，也可以从[发布页面](https://github.com/monedula-dev/monedula-sim-link/releases)获取适用于 Linux、macOS 和 Windows 的预编译二进制文件。它不发送任何遥测数据，并且是这套 URL 格式的参考生成器：它生成的链接在演练场中解码后，恰好就是它写入的那份日志。

## 像 Kafka 那样扩缩集群

自由模式现在会像真实集群那样改变 broker 数量。在 v1.9 之前，添加一个 broker 会悄悄地把分区再均衡到它上面 - 正如一位读者[指出的](https://github.com/monedula-dev/monedula-kafka-simulator-issues/issues/1)，这并不是 Kafka 的做法。现在你添加的 broker 加入时是空的：不会有任何分区自行迁移到它上面，集群检查器也会说明这一点，旁边还有一个 **Rebalance partitions** 按钮。在终端中，`kafka-reassign-partitions --generate` 会根据主题列表和 broker 列表提出一个方案，`--execute` 启动它，`--verify` 确认它。反方向也遵循同样的规则：仍持有分区的 broker 必须先被排空，才能被移除，顺序与你下线一个真实 broker 时相同。

打开[模拟器](/kafka-simulator/)，用 Cluster Linking 对一个区域执行故障切换，然后分享链接。