bigywater.tech
Spring · 125

Config Server 与 spring.config.import

Config Server 的配置到底怎么合并的?和本地的 application.properties 谁优先?服务端挂了客户端会怎样?git 里改了配置要不要重启?加密的配置是在哪里解密的?这篇用一个本地 git 仓库在 Spring Cloud Config 5.0.5 上逐项验证。

远程优先
客户端自己的 application.properties 里的同名 key 被 Config Server 的值覆盖
悄悄退回
spring.config.import=optional:configserver 连不上时用本地值,不报错
只拉一次
运行中的客户端看不到 git 里的新提交,要重启或 refresh

服务端接口

实测 · 本机执行输出
  GET /orders/default → 200,name=orders,profiles=['default'],label=None,propertySources(按优先级从高到低)= [('orders.properties', 2), ('application.properties', 2)]
  GET /orders/dev → 200,name=orders,profiles=['dev'],label=None,propertySources(按优先级从高到低)= [('orders-dev.properties', 1), ('orders.properties', 2), ('application.properties', 2)]
  GET /orders/dev/beta → 200,name=orders,profiles=['dev'],label=beta,propertySources(按优先级从高到低)= [('orders-dev.properties', 1), ('orders.properties', 2), ('application.properties', 2)]
  GET /orders-dev.properties → 200,内容(合并之后,按优先级): shared.key: shared-from-git ; greeting: hello-from-orders-dev ; orders.k: orders-k
  GET /nope/default(没有 nope.properties)→ 200,propertySources = [('application.properties', 2)]

应用名-profile 优先,其次应用名,最后 application;拼错应用名也是 200。

客户端导入

实测 · 本机执行输出
  客户端 spring.application.name=orders,不设 profile:greeting=hello-from-orders; shared.key=shared-from-git; orders.k=orders-k; local.only=yes; secret.pw=null;
  属性源(高到低):configurationProperties | servletConfigInitParams | configserver:file:///Users/w/Desktop/zen/tools/articles/jtmp/x125repo/orders.properties | configserver:file:///Users/w/Desktop/zen/tools/articles/jtmp/x125repo/application.properties | configClient | Config resource 'file [application.properties]' via location 'optional:file:./' | Config resource 'class path resource [application.properties]' via location 'optional:classpath:/' | applicationInfo
  spring.profiles.active=dev:greeting=hello-from-orders-dev; shared.key=shared-from-git; orders.k=orders-k; local.only=yes; secret.pw=null;
  spring.cloud.config.label=beta:greeting=hello-from-beta; shared.key=shared-from-git; orders.k=orders-k; local.only=yes; secret.pw=null;

spring.config.import 取配置,远程高于本地 application.properties;profile 与 label 传给服务端。

连不上

实测 · 本机执行输出
  optional:configserver,服务端没启动:客户端启动成功 → greeting=local-greeting; shared.key=null; orders.k=local-k; local.only=yes; secret.pw=null;
  去掉 optional:,服务端没启动:客户端启动失败(耗时 0.5 秒):Exception in thread "main" ConfigClientFailFastException: Could not locate PropertySource and the resource is not optional, failing | Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://127.0.0.1:9602/orders/default": Connection refused (connect failed)

optional 悄悄用本地值;去掉 optional 启动失败。

配置变更

实测 · 本机执行输出
  提交之后,服务端不重启,GET /orders/default 里的 greeting = hello-changed-in-git
  已经在运行的客户端不重启,GET /v 的 greeting:hello-from-orders(提交之前是 hello-from-orders)
  重启客户端之后 greeting = hello-changed-in-git

服务端实时读 git,客户端只在启动时拉一次。

加密

实测 · 本机执行输出
  POST /encrypt → 200,密文长度 64 个字符
  服务端 GET /orders/default 里 secret.pw = s3cret-pw
  客户端看到:secret.pw=s3cret-pw;
  服务端 encrypt.enabled=false:服务端返回的 secret.pw 以 {cipher} 开头(没有解密)
  客户端启动失败:Caused by: java.lang.UnsupportedOperationException: No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?

服务端解密后传明文;encrypt.enabled=false 时客户端没有密钥会启动失败。

分步演示

Config Server
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。Config Server 的后端是本地 git 仓库(file:// 路径,main 与 beta 两个分支);对称密钥 encrypt.key;客户端用 spring.config.import,没有用旧的 bootstrap 方式
    • 没有验证:远程 git(HTTPS / SSH)与认证;native 文件系统后端、Vault、JDBC 等其他后端;客户端 Basic 认证与 TLS;spring.cloud.config.server.git.refresh-rate 与 clone-on-start;多个仓库 / 按应用名分仓库;非对称密钥(keystore)加密;/actuator/refresh 与 Spring Cloud Bus(见第 126 篇);重试(spring.cloud.config.retry);高可用与服务发现方式连接 Config Server
    京ICP备2026067502号-1京公网安备11010502063487号