配置中心
把配置放到 Nacos 后,多个服务共用的数据库、Redis 等配置只需维护一份,修改后实时生效。tio-boot 应用读取 Nacos 配置的方式和读取 app.properties 完全一样,都是 EnvUtils.get*。
配置
nacos.server-addr=127.0.0.1:8848
nacos.namespace=hula-dev
nacos.username=nacos
nacos.password=nacos
# 按顺序加载,后面的覆盖前面的同名配置
nacos.config.data-ids=common.yml,demo-provider.ymlnacos.config.data-ids:要加载的配置,逗号分隔。以.yml/.yaml结尾的按 YAML 解析,其余按 properties 解析。nacos.config.group:分组,默认取nacos.group(DEFAULT_GROUP)。nacos.config.refresh-enabled:是否监听变更,默认true。nacos.config.timeout:首次读取的超时毫秒数,默认 5000。nacos.config.enabled:配置了 data-ids 时默认开启,设为false可以临时关闭。
启动时自动加载
引入 tio-boot-cloud-nacos 并配置 nacos.config.data-ids 后,不需要写任何代码。tio-boot 加载完 app.properties、命令行参数和环境变量后,会调用 classpath 中登记的 EnvLoadedListener,Nacos 模块在这里读取配置,时间早于 server.port 等服务配置的读取,所以 Nacos 中的配置可以控制整个启动过程,包括端口。
例如在 Nacos 中发布 demo-provider.yml:
server:
port: 18085
demo:
greeting: Port from Nacos不带任何参数启动,服务监听在 Nacos 中配置的 18085 端口:
environment listener nexus.io.tio.boot.cloud.nacos.NacosEnvLoadedListener
loaded nacos config demo-provider.yml (DEFAULT_GROUP)
registered demo-provider to nacos 127.0.0.1:8848 as 127.0.0.1:18085curl "localhost:18085/demo/hello?name=env"
{"data":{"instance":"127.0.0.1:18085","message":"Port from Nacos, env"},"code":1,"ok":true}应用的入口仍然只有一处 Nacos 调用:
package nexus.io.tio.boot.cloud.demo.provider;
import nexus.io.tio.boot.TioApplication;
import nexus.io.tio.boot.cloud.nacos.TioBootNacos;
public class ProviderApp {
public static void main(String[] args) {
TioApplication.run(ProviderApp.class, () -> {
TioBootNacos.start();
}, args);
}
}优先级
从高到低:
- 命令行参数
--key=value、系统属性-Dkey=value、环境变量。 - Nacos 配置,
nacos.config.data-ids中靠后的优先。 app.properties及app-{env}.properties等本地文件。
Nacos 中的配置覆盖本地文件,单个实例仍然可以在启动时用命令行或环境变量调整。
YAML 展开规则
YAML 按层级展开成点分隔的键,列表展开成带下标的键:
jdbc:
url: jdbc:mysql://127.0.0.1:3306/demo
gateway:
routes:
- id: user
uri: lb://user-service
predicates:
- Path=/api/user/**等价于:
jdbc.url=jdbc:mysql://127.0.0.1:3306/demo
gateway.routes[0].id=user
gateway.routes[0].uri=lb://user-service
gateway.routes[0].predicates[0]=Path=/api/user/**热更新
Nacos 中的配置修改后,客户端立即收到推送并更新 EnvUtils 中的值。每次请求都用 EnvUtils.get 读取的配置自动使用新值,例如上面的 demo.greeting:
curl "localhost:18080/api/provider/demo/hello?name=a"
{"data":{"instance":"127.0.0.1:18081","message":"Greetings v2, a"},"code":1,"ok":true}某个配置在 Nacos 中被删除后,恢复为本地 app.properties 中的值。
监听配置变更
启动时就创建好的对象(连接池、客户端等)需要在配置变化时重建,可以注册监听器,参数是变化的数据源和发生变化的键:
package nexus.io.tio.boot.cloud.demo.provider.config;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nexus.io.tio.boot.cloud.config.ConfigChangeListener;
import nexus.io.tio.utils.environment.EnvUtils;
public class GreetingChangeListener implements ConfigChangeListener {
private static final Logger log = LoggerFactory.getLogger(GreetingChangeListener.class);
@Override
public void onChange(String source, Set<String> changedKeys) {
if (changedKeys.contains("demo.greeting")) {
log.info("{} changed demo.greeting to {}", source, EnvUtils.get("demo.greeting"));
}
}
}package nexus.io.tio.boot.cloud.demo.provider.config;
import nexus.io.context.BootConfiguration;
import nexus.io.tio.boot.cloud.config.RemoteConfig;
import nexus.io.tio.boot.cloud.nacos.TioBootNacos;
public class ListenerConfig implements BootConfiguration {
@Override
public void config() throws Exception {
TioBootNacos.start();
RemoteConfig.addListener(new GreetingChangeListener());
}
}网关就是用同样的机制,在 gateway.routes 变化时重新加载路由。
在 Nacos 中存放公共配置
多个服务共用的配置放在一个公共 data id 中,各服务再加载自己的 data id:
# common.yml 放数据库、Redis 等公共配置,user-service.yml 放本服务自己的配置
nacos.config.data-ids=common.yml,user-service.yml注意 nacos.config.data-ids 本身要写在本地 app.properties、命令行或环境变量中,Nacos 连接信息同理。
