文章目录
- 配置管理
- 引入jar包
- 添加 bootstrap.yaml 文件配置
- 在application.yaml 中添加自定义信息
- nacos 配置信息
- 配置热更新
- 采用第一种配置
- 根据服务名确定配置文件
- 根据后缀确定配置文件
- 动态路由
- DynamicRouteLoader
- NacosConfigManager
- RouteDefinitionWriter
- 路由配置
配置管理
统一配置管理可以解决多服务配置过的问题,同时该服务配置文件移交配置中心 处理信息
引入jar包
配置 pom.xml 添加 config 和 bootstrap 的 jar 包
<!--nacos配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--读取bootstrap文件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
添加 bootstrap.yaml 文件配置
配置说明
spring.application.name: 指定微服务的名称(cart-service),Nacos 会根据该名称加载对应的配置。
spring.profiles.active: 指定当前激活的环境(dev),Nacos 会加载 cart-service-dev.yaml 配置。
spring.cloud.nacos.server-addr: 指定 Nacos 服务器的地址(127.0.0.1:8848)。
spring.cloud.nacos.config.file-extension: 指定配置文件的格式为 yaml。
spring.cloud.nacos.config.shared-configs: 定义共享配置,多个微服务可以共用这些配置。
spring:
application:
name: cart-service # 服务名称
profiles:
active: dev
cloud:
nacos:
server-addr: 127.0.0.1:8848
# nacos地址
config:
file-extension: yaml # 文件后缀名
shared-configs: # 共享配置
- dataId: shared-jdbc.yaml # 共享mybatis配置
- dataId: shared-log.yaml # 共享日志配置
- dataId: shared-swagger.yaml # 共享日志配置
在application.yaml 中添加自定义信息
hm:
db:
batabase: hm-cart
host: 127.0.0.1
port: 3306
username: root
password: password
nacos 配置信息
shared-log.yaml
logging:
level:
com.hmall: debug
pattern:
dateformat: HH:mm:ss:SSS
file:
path: "logs/${spring.application.name}"
shared-jdbc.yaml
spring:
datasource:
url: jdbc:mysql://${hm.db.host:127.0.0.1}:${hm.db.port:3306}/${hm.db.batabase}?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: ${hm.db.username}
password: ${hm.db.password}
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
global-config:
db-config:
update-strategy: not_null
id-type: auto
shared-swagger.yaml
knife4j:
enable: true
openapi:
title: ${hm.swagger.title:接口文档}
description: ${hm.swagger.desc:接口文档信息}
email: test
concat: test
url: test
version: v1.0.0
group:
default:
group-name: default
api-rule: package
api-rule-resources:
- ${hm.swagger.package}
配置热更新
当修改配置文件时,微服务无需重启即可生效
项目启动时 会去加载 相关配置 文件
Nacos 支持配置的动态更新。当配置文件在 Nacos 中修改后,应用会实时获取最新配置,无需重启。
采用第一种配置
@Data
@Component
@ConfigurationProperties(prefix = "hm.cart")
public class CartProperties {
private Integer maxItems;
}
nacos 配置 相关信息
根据服务名确定配置文件
在 Spring Cloud 应用中,Nacos 可以根据 spring.application.name 指定的服务名来加载对应的配置文件。例如:
服务名:user-service
Nacos 中的配置文件:user-service.properties 或 user-service.yaml
应用启动时,Nacos 会自动加载与服务名匹配的配置文件。
根据后缀确定配置文件
Nacos 还支持通过后缀来区分不同的配置文件。例如:
服务名:user-service
环境:dev
Nacos 中的配置文件:user-service-dev.properties 或 user-service-dev.yaml
在 Spring Cloud 中,可以通过 spring.profiles.active 指定环境后缀,Nacos 会加载对应环境的配置文件。
动态路由
要实现动态路由首先要将路由配置保存到Nacos,当Nacos中的路由配置变更时,推送最新配置到网关,实时更新网关中的路由信息。
我们需要完成两件事情:
- 监听Nacos配置变更的消息
- 当配置变更时,将最新的路由信息更新到网关路由表
DynamicRouteLoader
DynamicRouteLoader
是一个 Spring Cloud Gateway 的组件,用于从 Nacos 动态加载和更新路由配置。它通过监听 Nacos 配置中心的变化,实时更新网关的路由信息。
- DynamicRouteLoader 类:
- 负责从 Nacos 动态加载路由配置,并在配置发生变化时更新网关的路由表。
- 使用 NacosConfigManager 从 Nacos 获取配置数据,并监听配置变化。
- 依赖注入:
- NacosConfigManager:用于与 Nacos 配置中心交互,获取配置数据。
- RouteDefinitionWriter:用于更新 Spring Cloud Gateway 的路由定义。
- routeIds:用于存储当前已加载的路由 ID,方便后续更新时删除旧路由。
- 初始化方法 initRouteConfig:
- 在项目启动时调用(通过 @PostConstruct 注解)。
- 从 Nacos 获取初始的路由配置(dataId 为 gateway-routes.json,group 为 DEFAULT_GROUP)。
- 添加一个监听器,当 Nacos 中的配置发生变化时,自动调用 updateConfigInfo 方法更新路由。
- 配置更新方法 updateConfigInfo:
- 解析从 Nacos 获取的配置信息(JSON 格式),并将其转换为 RouteDefinition 对象列表。
- 删除旧的路由配置(通过 routeIds 中存储的路由 ID)。
- 清空 routeIds,然后遍历新的路由配置,将其保存到 RouteDefinitionWriter 中,并更新 routeIds。
package com.hmall.gateway.routers;
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {
private final NacosConfigManager nacosConfigManager;
private final RouteDefinitionWriter writer;
private final String dataId = "gateway-routes.json";
private final String group = "DEFAULT_GROUP";
private final Set<String> routeIds = new HashSet<>();
@PostConstruct
public void initRouteConfig() throws NacosException {
// 项目启动时, 拉取配置信息, 并添加监听器
String configInfo = nacosConfigManager.getConfigService()
.getConfigAndSignListener(dataId, group, 5000, new Listener() {
@Override
public Executor getExecutor() {
return null;
}
@Override
public void receiveConfigInfo(String configInfo) {
updateConfigInfo(configInfo);
}
});
// 读取到配置,更新路由表
updateConfigInfo(configInfo);
}
public void updateConfigInfo(String configInfo){
log.debug("监听获取路由配置信息:{}", configInfo );
// 解析配置信息, 转为RouteDefinition
List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);
// 删除旧的路由表信息
routeIds.forEach(e->{
writer.delete(Mono.just(e)).subscribe();
});
// 清空id 表
routeIds.clear();
// 遍历路由信息
for (RouteDefinition routeDefinition: routeDefinitions) {
// 更新路由表
writer.save(Mono.just(routeDefinition)).subscribe();
routeIds.add(routeDefinition.getId());
}
}
}
NacosConfigManager
NacosConfigManager 是 Spring Cloud Alibaba Nacos 提供的一个核心类,用于管理与 Nacos 配置中心的交互。它封装了 Nacos 配置客户端的操作,简化了从 Nacos 获取配置、监听配置变化等功能的实现。
NacosConfigManager 的作用
- 配置管理:
- 提供从 Nacos 配置中心获取配置的能力。
- 支持动态监听配置变化,实时更新本地配置。
- 简化操作:
- 封装了 Nacos 客户端的底层操作,开发者无需直接操作 Nacos 的原生 API。
- 与 Spring Cloud 集成:
- 作为 Spring Cloud Alibaba 的一部分,与 Spring Cloud 的配置管理机制无缝集成。
NacosConfigManager 的核心方法
获取配置
String getConfig(String dataId, String group, long timeoutMs) throws NacosException;
- 作用:从 Nacos 配置中心获取指定 dataId 和 group 的配置内容。
- 参数:
- dataId:配置的唯一标识符(如 gateway-routes.json)。
- group:配置的分组(如 DEFAULT_GROUP)。
- timeoutMs:获取配置的超时时间(毫秒)。
- 返回值:配置内容的字符串形式。
添加监听器
void addListener(String dataId, String group, Listener listener) throws NacosException;
- 作用:为指定 dataId 和 group 的配置添加监听器,当配置发生变化时触发回调。
- 参数:
- dataId:配置的唯一标识符。
- group:配置的分组。
- listener:监听器接口,实现 receiveConfigInfo 方法以处理配置变化。
获取 ConfigService
ConfigService getConfigService();
- 作用:获取底层的 ConfigService 对象,用于直接操作 Nacos 配置客户端。
- 返回值:ConfigService 实例。
RouteDefinitionWriter
RouteDefinitionWriter 是 Spring Cloud Gateway 提供的一个核心接口,用于动态管理路由定义(RouteDefinition)。它允许在运行时添加、删除或更新路由,从而实现动态路由的功能。
RouteDefinitionWriter 的作用
- 动态路由管理:
- 提供添加、删除和更新路由的能力。
- 支持在运行时修改路由配置,无需重启网关服务。
- 与 Spring Cloud Gateway 集成:
- 作为 Spring Cloud Gateway 的一部分,与网关的路由机制无缝集成。
- 响应式编程支持:
- 基于 Reactor 的响应式编程模型,所有操作返回
Mono<Void>
。
RouteDefinitionWriter 的核心方法
保存路由
Mono<Void> save(Mono<outeDefinition> route);
- 作用:保存一个路由定义。
- 参数:
- route:RouteDefinition 对象,表示一个路由规则。
- 返回值:
Mono<Void>
,表示操作完成后的信号。
删除路由
Mono<Void> delete(Mono<String> routeId);
- 作用:根据路由 ID 删除一个路由定义。
- 参数:
- routeId:路由的唯一标识符。
- 返回值:
Mono<Void>
,表示操作完成后的信号。
路由配置
在 nacos 中添加 gateway-routes.json 配置文件 信息 实现动态路由
id
: 路由的唯一标识符,值为 item。
uri
: 路由的目标服务地址,lb://item-service 表示通过负载均衡访问 item-service。
predicates
: 路由的匹配条件。
name
: 使用 Path 断言,表示根据请求路径匹配。
args
: 路径匹配规则。
_genkey_0
: /items/,匹配以 /items/ 开头的请求。
_genkey_1
: /search/,匹配以 /search/ 开头的请求。
filters
: 路由过滤器列表,当前为空。
[
{
"id": "item",
"uri": "lb://item-service",
"predicates": [{
"name": "Path",
"args": {
"_genkey_0": "/items/**",
"_genkey_1": "/search/**"
}
}],
"filters": []
},
{
"id": "user",
"uri": "lb://user-service",
"predicates": [{
"name": "Path",
"args": {
"_genkey_0": "/users/**",
"_genkey_1": "/addresses/**"
}
}],
"filters": []
},
{
"id": "cart",
"uri": "lb://cart-service",
"predicates": [{
"name": "Path",
"args": {
"_genkey_0": "/carts/**"
}
}],
"filters": []
}
]