bigywater.tech
微服务 · 57

配置的版本与回滚

配置改坏了怎么回滚?Nacos 的历史里存的是哪一版?删除之后还找得回来吗?两个人同时改同一份配置会不会互相覆盖?etcd 和 Consul 有没有历史?这篇用 Nacos 3.2.4、etcd 3.7.2 和 Consul 2.0.4 逐项试出来。

6 → 7 → 8
回滚到 v3 和撤销回滚后,Nacos 里这份配置的历史条数(回滚也是一次新发布)
a: 1 加 b: 2
两个编辑者各改一行、都不带 CAS 时的最终内容(编辑者 1 的修改丢了);带 cas_md5 后是 a: 2 加 b: 2
HTTP 400
etcd compact 之后按旧 revision 读的结果;Consul 带旧索引读得到的是当前值

Nacos 历史存了什么

实测 · 本机执行输出
  历史条目 id | opType | 修改时间(相对第一条,s) | 这条历史里的内容
  --------+--------+---------------+---------
  1       | I      | 0.0           | 'v1'    
  2       | U      | 0.4           | 'v1'    
  3       | U      | 0.8           | 'v2'    
  4       | U      | 1.1           | 'v3'    
  5       | U      | 1.4           | 'v4'    
  6       | U      | 1.7           | 'v5'    
  当前内容:'v6';历史共 6 条,发布了 6 次。每条历史里放的是那次修改“之前”的内容,所以最新的一版(当前内容)不在历史列表里,要回滚到某个旧版本,取的是比它晚一条的历史

U 记录存的是那次修改之前的内容,最新一版不在历史里;要回到某个版本取比它晚一条的历史。

回滚

实测 · 本机执行输出
  回滚(重新发布历史 id 4 的内容):HTTP 200;当前内容 'v3',md5 与 v3 原来的 md5 相同;历史从 6 条变成 7 条,最新一条(id 7)存的内容是 'v6'
  用最新一条历史的内容再发布一次(撤销回滚):当前内容 'v6';历史现在 8 条

回滚是把旧内容重新发布一次,md5 与原来相同,回滚之前的状态也进了历史。

删除之后

实测 · 本机执行输出
  DELETE:HTTP 200 {"code":0,"message":"success","data":true};删除之后当前内容:(HTTP 404 code 20004)
  历史条目 id | opType | 这条历史里的内容
  --------+--------+---------
  9       | I      | 'g1'    
  10      | U      | 'g1'    
  11      | D      | 'g2'    
  用删除记录里的内容重新发布:HTTP 200;当前内容 'g2'(删除之前最后一版是 g2)

删除记录里存着删除之前的最后一版,可以用它恢复。

并发编辑

实测 · 本机执行输出
  场景           | 操作                  | publish_config 返回                                                             | 备注               
  -------------+---------------------+-------------------------------------------------------------------------------+------------------
  (a)不带 CAS    | 编辑者 1 发布            | True                                                                          |                  
  (a)不带 CAS    | 编辑者 2 发布            | True                                                                          | 最终内容 'a: 1\nb: 2'
  (b)带 cas_md5 | 编辑者 1 发布(md5 与当前一致) | True                                                                          |                  
  (b)带 cas_md5 | 编辑者 2 发布(md5 已过期)   | 'NacosException: Error [500]: Cas publish fail, server md5 may have changed.' |                  
  (b)带 cas_md5 | 编辑者 2 重新读取、合并、再发布   | True                                                                          | 最终内容 'a: 2\nb: 2'
  另一个观察:用 SDK 发布 c0 后立刻 get_config 得到 '',1.5 s 后得到 'c0';再用 SDK(带 cas_md5)发布 c1,立刻 get_config 得到 'c0',1.5 s 后得到 'c1'。所以上面的读取都走管理 API
  顺带一个观察:管理 API 的 POST 带 casMd5=deadbeef(明显不对的 md5)发布,返回 HTTP 200 {'code': 0, 'message': 'success', 'data': True};当前内容 'y'。这个参数名在这个版本的管理 API 上没有起作用(我没有查正确的参数名),要用 CAS 就走 SDK

不带 CAS 后发布的会覆盖先发布的;带 cas_md5 过期的发布会被拒绝,需要重新读取合并再发布。

etcd 与 Consul

实测 · 本机执行输出
  操作                                     | 结果                                                             
  ---------------------------------------+----------------------------------------------------------------
  按 revision 3 读(未压缩)                    | v2                                                             
  compact 到 revision 6 之后,按 revision 3 读 | HTTP 400 etcdserver: mvcc: required revision has been compacted
  compact 之后,按 revision 6 读              | HTTP 200 v5                                                    
  key 的元数据:version=5(这个 key 被写了几次),create_revision=2,mod_revision=6(全局 revision);五次写入的 revision:[2, 3, 4, 5, 6]
  Consul:写了 v1(ModifyIndex 17)和 v2;用 index=16(早于 v1 的修改)读,0 ms 后返回的是 ModifyIndex 18 的值 'v2';也就是说带旧索引读(blocking query 的 index 参数)得到的是当前值,不是旧版本。我没有在文档或其他接口里找按旧版本读的办法(没有穷尽)
ERRORS {}

etcd 能按旧 revision 读,但压缩后读不到;Consul 带旧索引读得到的是当前值。

分步演示

配置的版本与回滚
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / Go / nginx / Envoy / etcd / Consul / Nacos / OpenTelemetry / Prometheus(按各篇注明用到哪些及版本);所有服务都是本机自己起的进程,端口 9150 以上,只监听 127.0.0.1,不连任何外部服务,不碰本机已有的实例;故障用 kill -9 进程、让连接断开或在代码里注入延迟与错误来制造;计时用 time.perf_counter,数字每次运行会有小幅抖动。Nacos 3.2.4(单机,Java 17),发布、历史、删除用 /nacos/v3/admin/cs/ 下的管理 API,CAS 用 nacos-sdk-python 3.2.0;etcd 3.7.2 单节点;Consul 2.0.4 单节点;每项各测 1 次(这些是确定性的操作,不是性能数字)
    • 没有验证:Nacos 历史的保留时间和清理(我印象里默认保留 30 天,没有验证);历史条目的数量上限;灰度发布(beta)与按 tag 的配置;Nacos 配置的权限与审计;管理 API 正确的 CAS 参数名(试了 casMd5 无效);配置内容很大时的历史开销;etcd 的自动压缩配置;Consul 里除了 index 参数之外是否有别的读旧版本的办法(没有穷尽)
    京ICP备2026067502号-1京公网安备11010502063487号