Skip to content

配置中心 ​

把配置放到 Nacos 后,多个服务共用的数据库、Redis 等配置只需维护一份,修改后实时生效。tio-boot 应用读取 Nacos 配置的方式和读取 app.properties 完全一样,都是 EnvUtils.get*。

配置 ​

properties
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.yml
  • nacos.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:

yaml
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:18085
shell
curl "localhost:18085/demo/hello?name=env"
{"data":{"instance":"127.0.0.1:18085","message":"Port from Nacos, env"},"code":1,"ok":true}

应用的入口仍然只有一处 Nacos 调用:

java
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);
  }
}

优先级 ​

从高到低:

  1. 命令行参数 --key=value、系统属性 -Dkey=value、环境变量。
  2. Nacos 配置,nacos.config.data-ids 中靠后的优先。
  3. app.properties 及 app-{env}.properties 等本地文件。

Nacos 中的配置覆盖本地文件,单个实例仍然可以在启动时用命令行或环境变量调整。

YAML 展开规则 ​

YAML 按层级展开成点分隔的键,列表展开成带下标的键:

yaml
jdbc:
  url: jdbc:mysql://127.0.0.1:3306/demo
gateway:
  routes:
    - id: user
      uri: lb://user-service
      predicates:
        - Path=/api/user/**

等价于:

properties
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:

shell
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 中的值。

监听配置变更 ​

启动时就创建好的对象(连接池、客户端等)需要在配置变化时重建,可以注册监听器,参数是变化的数据源和发生变化的键:

java
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"));
    }
  }
}
java
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:

properties
# common.yml 放数据库、Redis 等公共配置,user-service.yml 放本服务自己的配置
nacos.config.data-ids=common.yml,user-service.yml

注意 nacos.config.data-ids 本身要写在本地 app.properties、命令行或环境变量中,Nacos 连接信息同理。

MIT Licensed