首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
etcd 健壮性测试报告出现 Linearization illegal 时怎么分析和重新评估
📅 2026/9/13 18:28:11
✍️ 爱科研究院
👁 阅读 3,247
etcd 健壮性测试报告出现 Linearization illegal 时怎么分析和重新评估【免费下载链接】etcdDistributed reliable key-value store for the most critical data of a distributed system项目地址: https://gitcode.com/GitHub_Trending/et/etcd运行 etcd 健壮性测试make test-robustness时如果测试失败并打出ERROR Linearization illegal日志说明采集到的客户端 KV 操作历史无法按 etcd 模型线性化框架会立即跳过后续的 watch 和 serializable 校验。本文按 tests/robustness/README.md 给出的官方示例走一遍完整处理路径先定位失败报告再用history.html判断到底违反了哪条 API 保证最后把报告放进testdata用新版本的校验逻辑重新评估。操作需要 Go 工具链和 make。1. Linearization illegal 是怎么产生的健壮性测试的完整流程是创建 etcd 集群 → 注入流量与故障 → 记录所有客户端操作和结果 → 用 etcd 模型加一组校验器验证历史 → 失败时生成报告。其中线性化校验在 tests/robustness/validate/operations.go 中实现把可线性化的 KV 操作交给 porcupine 的CheckOperationsVerbose执行超时时间 5 分钟。结果分三种porcupine.Ok→ 日志Linearization successporcupine.Unknown→ 日志Linearization timed out这是超时不是违规结论且不会产生可视化见 validate_test.go 中TestLinearizationVisualizeSkipsTimeout的断言porcupine.Illegal→ 日志Linearization illegal即本文讨论的错误出现Linearization illegal后validate.go 会直接返回并打印Skipping other validations as linearization failed——watch 和 serializable 校验被跳过因为它们预计也会失败只会搅乱日志。所以看到这个错误时先解决线性化问题。进入线性化校验的操作范围也有边界出错的只读请求和 Defragment 不参与线性化失败请求的返回时间被设为MaxInt64因为无法确定它何时生效。etcd 对 KV 操作提供 strict serializability并保证 revision 非递减。线性化校验就是在验证记录下来的请求/响应是否符合这些约束。文档中的错误日志示例文档示例logger.go:146: 2025-08-01T22:54:26.5500900 INFO Validating linearizable operations {timeout: 5m0s} logger.go:146: 2025-08-01T22:54:26.7550900 ERROR Linearization illegal {duration: 205.05225ms} logger.go:146: 2025-08-01T22:54:26.7550900 INFO Skipping other validations as linearization failed main_test.go:122: linearization: illegal logger.go:146: 2025-08-01T22:54:26.7560900 INFO Saving robustness test report {path: /tmp/TestRobustnessRegression_Issue14370/1754056466755991000}2. 定位失败报告2.1 本地运行报告路径直接写在日志里找Saving robustness test report这一行示例中即/tmp/TestRobustnessRegression_Issue14370/1754056466755991000。注意默认只在测试失败时生成报告想让成功运行也保留报告可设置环境变量PERSIST_RESULTS报告保存根目录可用RESULTS_DIR修改默认在/tmp/下目录名由测试名和时间戳组成见 main_test.go 的testResultsDirectory。通用运行方式是先在 tests/robustness/Makefile 中定义的流程里构建带 failpoint 的二进制再跑测试make gofail-enable make build make gOFAIL-disablegofail-enable会在server/etcdserver/、server/storage/、server/lease/等目录源码中插入 failpoint 钩子并在 server、etcdutl、etcdctl、tests 几个子模块中执行go get go.etcd.io/gofail版本版本取自 tools/mod 的 go.modgofail-disable撤销这些修改并执行go mod tidy。也就是说这两条命令会临时改写仓库源码树跑完测试后务必执行gofail-disable恢复。make test-robustness还可以用环境变量控制行为GO_TEST_FLAGS传额外参数给go testREADME 建议多次运行并开启 failfast例如GO_TEST_FLAGS--count100 --failfastEXPECT_DEBUGtrue获取集群日志TRACING_SERVER_ADDR把 OpenTelemetry trace 导出到指定地址的 collector。2.2 官方复现示例issue #14370要自己产出一份包含Linearization illegal的报告README 给出的路径是复现已知问题 #14370make test-robustness-issue14370副作用和使用前提需要说清楚该 target定义在 tests/robustness/Makefile依赖/tmp/etcd-v3.5.4-failpoints/bin构建规则会先删除/tmp/etcd-v3.5.4-failpoints/这个临时目录的旧内容再从官方仓库克隆 v3.5.4 到该位置、启用 failpoint 并构建因此需要网络访问且过程较慢。之后它会以--runTestRobustnessRegression/Issue14370 --count 100 --failfast运行回归子测试。README 说明对于这个历史版本After a couple of tries robustness tests should fail with a logLinearization illegaland save the report locally。该 target 最后会打印Successful reproduction或Failed to reproduce前者即测试失败、问题被复现。2.3 CI 上的报告对于 CI 远端运行进入 Prow Dashboard地址见 tests/robustness/README.md打开一个 build下载 artifactartifacts/results.zip并解压。压缩包内每个目录都以TestRobustness为前缀各包含一份健壮性测试报告。按体积最大的目录通常就是失败的场景不确定时可以查看测试日志确认哪个场景失败。2.4 报告目录结构无论本地还是 CI报告目录结构一致server-*etcd 服务端数据目录可用于核查磁盘/内存损坏member/walWAL 目录可用tools目录下的etcd-dump-logs工具分析见 tools/etcd-dump-logs/README.mdmember/snap快照目录包含 bbolt 数据库文件db可用etcd-dump-db工具分析见 tools/etcd-dump-db/README.mdclient-*客户端请求/响应的 JSON 转储watch.jsonwatch 请求和响应用于核对 watch API guaranteesoperations.jsonKV 操作历史history.htmlKV 操作历史的可视化用于核对 KV API guarantees3. 用 history.html 分析 Linearization illegalREADME 的结论是线性化问题最容易通过历史可视化来分析。以 2.2 节产生的报告为例用浏览器打开/tmp/TestRobustnessRegression_Issue14370/1754056466755991000/history.html页面顶部点击[ jump to first error ]跳到线性化的首个错误处。文档示例中文档示例数值来自 README 对 issue #14370 的分析最后一个正确的请求灰线是一个成功且得到 revision168的Put之后所有请求红线都是非法的因为它们的 revision 是167。etcd 保证 revision 非递减revision 回退说明这是 etcd 侧的 bug——这与 #14370 的根因一致进程崩溃导致最后一次写入丢失。你自己的报告不要套用 168/167 这两个数值以跳转到的位置处实际请求、响应和 revision 为准看最后一个合法请求与首个非法请求之间的差异判断违反了哪条 KV API guarantee如果怀疑损坏与数据目录有关再结合server-*目录做核查。4. 用新校验逻辑重新评估报告README 专门说明了重新评估的动机健壮性测试的校验逻辑在不断演进etcd 模型自身的错误可能产生假阳性因此修复后要能用新版逻辑重评旧报告。步骤把报告目录复制进tests/robustness/testdata该目录可放多份报告目录名随意但必须唯一避免与已有报告冲突。README 给出的示例路径形如tests/robustness/testdata/v3.5_failure_24_April/history.html。命令示意如下/path/to/report-dir替换为你日志里Saving robustness test report给出的实际报告目录cp -r /path/to/report-dir tests/robustness/testdata/v3.5_failure_24_April运行重新评估target 定义在 tests/robustness/Makefile按其所在目录执行即可例如make -C tests/robustness test-robustness-reportsmake test-robustness-reports该 target 会按仓库根目录.go-version文件钉住 Go 工具链版本实际执行cd tests go test ./robustness/validate -v --count 1 --run TestDataReports。重新评估做的事validate_test.go 中的TestDataReports遍历testdata下每个子目录加载客户端报告和集群持久化请求用当前版本的完整校验链线性化、watch、serializable重新验证并在报告目录内重新生成history.html。判断标准对应报告的子测试通过说明按当前校验逻辑该报告合法原来的Linearization illegal可能是模型问题导致的假阳性仍失败则说明历史在当前模型下依旧违规需要继续按第 3 节方式定位。5. 已知限制报告格式不稳定README 明确Robustness test report format is not stable, and its expected that not all old reports can be re-evaluated using the newest version。无法重评的旧报告只能重新跑测试生成新报告。默认只在失败时生成报告成功运行需要PERSIST_RESULTS才会保留。线性化校验超时是 5 分钟超时结果是Linearization timed out而非Linearization illegal两者含义不同且超时不产生可视化。make test-robustness-issueNNNNN系列命令用于确认历史问题是否仍可复现依赖从网络克隆指定版本并在/tmp下构建不适合作为日常回归手段日常回归用make test-robustness或各 release 分支对应的test-robustness-release-*target。处理完一条报告后的落点如果history.html显示违反 guarantee如 revision 回退按报告中的server-*数据目录继续核查 etcd 侧根因如果怀疑是校验模型假阳性把报告放进testdata等校验逻辑修复后用make test-robustness-reports重新给出结论。【免费下载链接】etcdDistributed reliable key-value store for the most critical data of a distributed system项目地址: https://gitcode.com/GitHub_Trending/et/etcd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/9/13 18:28:11
使用 WebdriverIO 编写第一个 Appium JavaScript 测试:Node.js 快速上手指南
2026/9/13 18:28:11
react-email editor 文本对齐修复深度解析:Left 按钮激活态、显式对齐持久化与祖先继承解析
2026/9/13 18:28:11
PostHog SceneMenuBar 场景菜单栏迁移指南:从 ScenePanel 到 Mac 风格菜单栏的双写改造实践
2026/9/13 19:08:13
先进封装测试:热-力-电耦合驱动的芯片质量新范式
2026/9/13 19:08:13
嵌入式三大硬门槛:硬件信号、C语言工程化与行业系统思维
2026/9/13 19:08:13
星辰300如何实现边缘端高效人脸检测
2026/9/13 19:08:13
OpenClaw Amazon Bedrock Provider 插件全解析:模型发现、Embedding 与 Guardrail 支持
2026/9/13 19:08:13
Lexe Lambda 冷启动优化完整清单:把冷启动压到 64ms
2026/9/13 19:03:13
MAA 集成战略(肉鸽)自动作战全指南:主题开局、战斗策略与异常容错
2026/9/13 0:01:25
拯救者Y7000黑屏故障排查与维修实战指南
2026/9/13 0:01:25
AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验
2026/9/13 0:01:25
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化
2026/9/13 0:01:25
拯救者Y7000黑屏故障排查与维修实战指南
2026/9/13 0:01:25
AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验
2026/9/13 0:01:25
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化