Nacos 客户端如何使用本地 failover 文件在服务端不可用时降级读取配置?
【免费下载链接】nacosan easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications.项目地址: https://gitcode.com/GitHub_Trending/na/nacos
当 Nacos 服务端宕机或网络中断时,Java 客户端仍可通过一份由用户手工维护的本地 failover 文件读取指定配置项的内容。本文基于 Nacos 客户端源码与本地缓存规范,说明 failover 文件的路径规则、放置方法、如何验证降级生效,以及它和 snapshot 缓存的优先级关系。
读取优先级:failover 文件排在服务端之前
Nacos 客户端读取一条配置的顺序在 客户端本地缓存与 Redo 规范 中明确定义为三级:
- 用户维护的本地 failover 文件;
- 服务端查询;
- 本地 snapshot。
关键点在第 NacosConfigService.getConfigInner 的实现:failover 文件在发起服务端查询之前就被检查,存在即直接返回其内容,根本不会去连服务端。这正是"服务端不可用也能读到配置"的机制来源——不是请求失败后的兜底,而是最高优先级的本地读取。
同时规范明确了两条边界:
- failover 文件不会由客户端自动创建,完全由用户维护;
- failover 内容不会自动写回服务端,它只对本地读取生效,服务端数据不受影响。
failover 文件放在哪里
路径由 LocalConfigInfoProcessor 的静态常量与getFailoverFile方法决定:
- 基础目录:若设置了系统属性
JM.SNAPSHOT.PATH,以它的值为根;否则使用user.home(即用户主目录)。在其后追加固定子目录nacos/config。默认即~/.nacos/config。 - 第一级目录名是客户端连接的服务端地址字符串(agent name,如
127.0.0.1:8848)。源码中超过长度上限的地址会被simplyEnvNameIfOverLimit截断,因此长地址拼接的多节点地址字符串对应的目录名可能与原值不完全一致。 - 第二级区分是否带 namespace(tenant):
| 配置坐标 | 相对~/.nacos/config的 failover 路径 |
|---|---|
无 namespace,group 为DEFAULT_GROUP,dataId 为demo.properties | 127.0.0.1:8848/data/config-data/DEFAULT_GROUP/demo.properties |
namespace 为abc123,其余相同 | 127.0.0.1:8848/data/config-data-tenant/abc123/DEFAULT_GROUP/demo.properties |
对应源码规则见 getFailoverFile:tenant 为空时走data/config-data/{group}/{dataId},tenant 非空时走data/config-data-tenant/{tenant}/{group}/{dataId}。文件内容就是配置原文,直接以文本形式写入即可。
操作步骤
以客户端连接127.0.0.1:8848、dataId 为demo.properties、group 为DEFAULT_GROUP、无 namespace 为例。以下命令中把127.0.0.1:8848、DEFAULT_GROUP、demo.properties替换为你实际的地址与配置坐标:
# 1. 创建 failover 目录(无 namespace 的情况) mkdir -p ~/.nacos/config/127.0.0.1:8848/data/config-data/DEFAULT_GROUP # 2. 写入配置原文作为 failover 文件 cat > ~/.nacos/config/127.0.0.1:8848/data/config-data/DEFAULT_GROUP/demo.properties <<'EOF' key1=value1 key2=value2 EOF带 namespace 时,目录改为~/.nacos/config/127.0.0.1:8848/data/config-data-tenant/{namespaceId}/DEFAULT_GROUP/。
创建文件后有两种生效方式,取决于应用是否已在运行:
- 应用启动前放置:进程启动后第一次
getConfig调用直接命中 failover。 - 应用运行中放置或修改:客户端的 listener 检查任务会在每轮 listener check 前调用 checkLocalConfig 检查 failover 文件,文件"出现、变化、消失"三种状态都会被感知,并按
CacheData的 MD5 规则更新已注册 listener 的内容。因此运行中修改 failover 文件同样会被 listener 感知,无需重启应用。
验证降级是否生效
读取验证:在应用内调用ConfigService.getConfig(dataId, group, timeoutMs),返回值应与 failover 文件内容一致。命中 failover 时不会发起服务端查询,即使服务端不可用也不抛异常。
日志验证:以下日志格式来自源码中的日志语句({}位置在实际日志中为具体值),可用于在客户端日志中确认走了哪条路径:
# 命中 failover(WARN 级别) [127.0.0.1:8848] [get-config] get failover ok, dataId=demo.properties, group=DEFAULT_GROUP, tenant= # 未命中 failover 且服务端查询失败(WARN 级别),随后回落到 snapshot [127.0.0.1:8848] [get-config] get from server error, ... [127.0.0.1:8848] [get-config] get snapshot ok, ...日志前缀是服务端地址(agent name),get failover ok表示本次读取由 failover 文件提供;如果看到get from server error加get snapshot ok,说明没有 failover 文件、客户端在用服务端查询成功时缓存下来的本地 snapshot 兜底——这是与 failover 完全不同的数据源,内容为最后一次成功查询的旧值。
listener 验证:运行中的应用注册了 listener 后增删改 failover 文件,客户端会输出(格式同样来自源码):
[127.0.0.1:8848] [failover-change] failover file created. dataId=demo.properties, group=DEFAULT_GROUP, tenant=, md5=... [127.0.0.1:8848] [failover-change] failover file changed. dataId=demo.properties, group=DEFAULT_GROUP, tenant=, md5=... [127.0.0.1:8848] [failover-change] failover file deleted. dataId=demo.properties, group=DEFAULT_GROUP, tenant=其中md5为 failover 文件内容的 MD5 值,可在实际日志中对照;listener 是否收到回调按CacheData的 MD5 变化规则触发,见 checkLocalConfig 与规范第 2 节的描述。
边界与限制
- failover 优先级高于可用服务端:只要 failover 文件存在,即使服务端正常,
getConfig也返回 failover 内容。想恢复服务端数据,删除对应 failover 文件即可,failover file deleted日志出现后客户端切回服务端配置。 - 不自动写回:failover 内容只影响本地读取。若希望这份内容成为服务端数据,需要在服务端恢复后另行发布。
- 加密配置:encrypted data key 的本地 failover 与 snapshot 由 LocalEncryptedDataKeyProcessor 单独维护,目录为
failover/failover-tenant,与配置内容文件分开存放;使用加密配置时需要一并考虑。 - snapshot 的区别:snapshot 在服务端查询成功后写入、在服务端确认配置项不存在时删除,是"恢复缓存";failover 是用户主动维护的紧急覆盖。两者不可混用。
- 文件不会被客户端删除:按规范第 9 节,SDK shutdown 不应删除用户维护的 failover 文件或服务端派生 snapshot。
- 命名空间维度的隔离:tenant 为空与 tenant 非空是两套目录(
config-data与config-data-tenant),放错目录会导致 failover 不生效。 - Naming(服务发现)也有一套 failover 机制,但它是本地 discovery 视图覆盖,与本文的配置 failover 文件不是同一功能,不要用配置 failover 文件去修服务端数据。
进一步阅读
- 规范全文:客户端本地缓存与 Redo 规范
- 客户端本地数据分类与优先级定义见该规范第 1、2 节
- 路径构造实现:LocalConfigInfoProcessor
- 读取主流程实现:NacosConfigService
- 相关测试用例:LocalConfigInfoProcessorTest、NacosConfigServiceTest
【免费下载链接】nacosan easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications.项目地址: https://gitcode.com/GitHub_Trending/na/nacos
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考