将一个大项目拆解成多个微服务时,就会导致:①微服务重复配置过多②业务配置经常变动,每次修改都要重启服务③网关配置写死,如果变更需要重启网关Nacos不仅有注册中心的功能,针对以上问题,Nacos还提供了配置管理功能1 添加配置到Nacos添加一些共享配置到Nacos中,比如JDBC,MybatisPlus,日志(logback.xml)等spring: datasource: #mysql数据源 driver-class-name: com.mysql.cj.jdbc.Driver type: com.zaxxer.hikari.HikariDataSource #SpringBoot(默认)数据源,如果使用其他数据源需(dbcp2等)要额外导包 url: jdbc:mysql://${customize.nacos-configuration.datasource.url}?rewriteBatchedStatementstrue #engineering是数据库名 rewriteBatchedStatementstrue支持(插入)批处理 username: ${customize.nacos-configuration.datasource.username} password: ${customize.nacos-configuration.datasource.password}2 拉取配置2.1 基于NacosConfig拉取配置基于NacosConfig拉取共享配置代替本地微服务的配置,把原本基于SpringBoot加载配置文件的方式改为SpringCloud加载配置文件的方式2.2 引入依赖(注意: com.alibaba.cloud依赖的版本要2023.0.1.3及以上)!--nacos配置管理,nacosConfig-- dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependency !--读取bootstrap文件-- dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-bootstrap/artifactId dependency2.3 创建bootstrap.yaml文件spring: application: name: selfDeveloped-----dev profiles: active: dev cloud: nacos: server-addr: 123.123.123.123:8848 # config: # import-check: # enabled: false #(默认为true)如果项目导了spring-cloud-starter-alibaba-nacos-config依赖,但又不需要配置中心,就需要在此处说明不需要检查配置中心 config: import: - nacos:selfDeveloped.yaml - nacos:share-datasource.yaml - nacos:share-mybatis-plus.yaml - nacos:share-seata.yaml3 配置热更新修改nacos中的配置时,微服务无需重启即可实时获取最新配置首先,在项目的bootstrap.yaml中引入对应配置管理spring: cloud: nacos: server-addr: 123.123.123.123:8848 config: import: - nacos:abc.yamlabc.yamlaaa: bbb: one: 爱丽丝 two: 安利康师傅3.1 微服务接收热更新数据(方式一)Prop类ConfigurationProperties(prefix aaa.bbb)注解Component ConfigurationProperties(prefix aaa.bbb) public class TestProp { private String one; private String two; public String getOne() { return one; } public void setOne(String one) { this.one one; } public String getTwo() { return two; } public void setTwo(String two) { this.two two; } }在对应的xxxServiceImpl类中用Autowired注入成员变量,该成员变量就能接收热更新数据Autowired private TestProp testProp;3.2 微服务接收热更新数据(方式二)RefreshScope注解Value(${aaa.bbb.ccc})注解在对应的xxxServiceImpl类用RefreshScope注解,同时用Value(${aaa.bbb.ccc})注入成员变量,该成员变量就能接收热更新数据Service Transactional RefreshScope public class GuardNetServiceImpl { Value(${aaa.bbb.one}) private String one; Value(${aaa.bbb.two}) private String two;4 动态路由网关启动时,会加载配置文件中的路由信息,然后保存在路由表(缓存)中,之后在处理请求的路由转发时,就无须再去读取配置文件,而是直接读取缓存即可但这样就会存在一个问题,即使将gateway模块的配置文件的路由信息写在nacos中,而且能实现配置热更新,也无法做到路由表的实时更新(因为路由表只在网关启动时读取配置文件,后续对配置文件的热更新不会再被重新读取)4.1 动态路由实现原理① 路由配置保存到nacos,通过配置热更新原理,能实时将最新的路由信息更新到网关gateway模块② 在gateway模块中监听nacos的配置变更,将变更的路由信息更新到路由表4.2 gateway模块引入依赖!--nacos配置管理,nacosConfig-- dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId version2023.0.1.2/version /dependency !--读取bootstrap文件-- dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-bootstrap/artifactId /dependency4.3 新建动态路由加载器类,做路由配置变更监听package xyz.aboluo.gateway.routers; import com.alibaba.cloud.nacos.NacosConfigManager; import com.alibaba.nacos.api.config.listener.Listener; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionWriter; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Executor; import com.alibaba.fastjson2.JSON; import reactor.core.publisher.Mono; Component public class DynamicRouteLoader { Autowired private NacosConfigManager nacosConfigManager; Autowired private RouteDefinitionWriter routeDefinitionWriter; Autowired private ApplicationEventPublisher applicationEventPublisher; private final String dataId gateway-route-dev.json; private final String group DEFAULT_GROUP; private SetString routeIds new HashSet(); PostConstruct // 在类被初始化进SpringIOC容器时,就调用此方法 public void initRouteConfigListener() throws Exception { // 拉取NacosConfig配置并添加监听器 String configInfo nacosConfigManager.getConfigService() .getConfigAndSignListener(dataId, group, 5000, new Listener() { Override public Executor getExecutor() { return null; } Override public void receiveConfigInfo(String s) { // 监听到配置变更,更新到路由表 updateConfigInfo(s); } }); // 首次启动时,将拉取的配置信息更新到配置表 updateConfigInfo(configInfo); } public void updateConfigInfo(String configInfo) { // 删除旧的路由表 for (String routeId : routeIds) { routeDefinitionWriter.delete(Mono.just(routeId)).subscribe(); } routeIds.clear(); // 更新路由表 for (RouteDefinition routeDefinition : JSON.parseArray(configInfo, RouteDefinition.class)) { // 更新路由表 routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe(); // 记录路由id,便于下次更新时删除旧的路由表 routeIds.add(routeDefinition.getId()); } // 发布路由 applicationEventPublisher.publishEvent(new RefreshRoutesEvent(routeDefinitionWriter)); } }4.4 在nacos配置管理中新建路由规则的json格式配置路由规则的json格式与yaml格式对照关系: