Hello,大家好,我是 V 哥。最近写到 使用 Nacos 实现动态路由的问题,整理了一下思路和案例,分享给大家。
使用 Nacos 实现 Spring Cloud Gateway 的动态路由,主要涉及到以下几个步骤:
- 添加依赖:在 Spring Cloud Gateway 应用的
pom.xml
文件中添加 Nacos 相关依赖。 - 配置 Nacos:在
application.yml
或application.properties
文件中配置 Nacos 服务地址。 - 启用动态路由:在配置文件中启用 Nacos 动态路由功能。
- 创建动态路由配置:在 Nacos 配置中心创建动态路由的配置信息。
- 监听配置变化:在 Spring Cloud Gateway 应用中监听 Nacos 配置变化,动态更新路由规则。
下面是具体的实现步骤和代码案例,来看一下:
1. 添加依赖
在 pom.xml
文件中添加 Spring Cloud Gateway 和 Nacos 相关依赖:
<dependencies>
<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Spring Cloud Alibaba Nacos Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Spring Cloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
2. 配置 Nacos
在 application.yml
文件中配置 Nacos 服务地址:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 服务地址
config:
server-addr: 127.0.0.1:8848 # Nacos 配置中心地址
file-extension: yml # 配置文件格式
group: DEFAULT_GROUP # 配置分组
namespace: # 配置命名空间
3. 启用动态路由
在 application.yml
文件中启用 Nacos 动态路由功能:
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能
lower-case-service-id: true # 使用小写服务名,默认是大写
4. 创建动态路由配置
在 Nacos 配置中心创建一个配置文件,例如 gateway-routes.yml
,内容如下:
spring:
cloud:
gateway:
routes:
- id: my-service-route
uri: lb://MY-SERVICE
predicates:
- Path=/my-service/**
filters:
- StripPrefix=1
5. 监听配置变化
在 Spring Cloud Gateway 应用中,创建一个配置类来监听 Nacos 配置变化,并刷新路由规则:
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class DynamicRouteService {
private final RouteDefinitionWriter routeDefinitionWriter;
private final RouteDefinitionLocator routeDefinitionLocator;
public DynamicRouteService(RouteDefinitionWriter routeDefinitionWriter,
RouteDefinitionLocator routeDefinitionLocator) {
this.routeDefinitionWriter = routeDefinitionWriter;
this.routeDefinitionLocator = routeDefinitionLocator;
}
@EventListener
public void onEnvironmentChange(EnvironmentChangeEvent event) {
if (event.getKeys().contains("spring.cloud.gateway.routes")) {
routeDefinitionLocator.getRouteDefinitions()
.subscribe(routeDefinitions -> {
routeDefinitionWriter.delete("*").subscribe();
routeDefinitionWriter.save(routeDefinitions).subscribe();
});
}
}
}
这个类会监听环境变化事件,当检测到 spring.cloud.gateway.routes
配置项发生变化时,会重新加载和刷新路由规则。
我们通过使用 Nacos 实现 Spring Cloud Gateway 的动态路由。通过在 Nacos 配置中心维护路由配置,可以实现不重启网关服务的情况下动态更新路由规则,这对于微服务架构中的服务治理非常有用。
在使用 Nacos 动态路由时,如果服务下线了,Spring Cloud Gateway 会如何响应?
当使用 Nacos 动态路由时,如果服务下线,Spring Cloud Gateway 会通过 Nacos 的服务发现机制感知到这一变化,并根据配置的动态路由规则进行调整。如何配置 Spring Cloud Gateway 以响应服务下线的情况呢?来,上代码:
首先,确保咱们的项目中已经添加了 Spring Cloud Gateway 和 Spring Cloud Alibaba Nacos Discovery 的依赖。
1. application.yml 配置
在 application.yml
中配置 Nacos 服务发现和动态路由:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 服务地址
gateway:
routes:
- id: my-service-route
uri: lb://MY-SERVICE
predicates:
- Path=/my-service/**
filters:
- StripPrefix=1
discovery:
locator:
enabled: true
lower-case-service-id: true
2. Nacos 配置中心的动态路由配置
在 Nacos 配置中心创建一个名为 gateway-routes.json
的配置文件,内容如下:
{
"spring": {
"cloud": {
"gateway": {
"routes": [
{
"id": "my-service-route",
"uri": "lb://MY-SERVICE",
"predicates": [
{
"name": "Path",
"args": {
"_genkey_0": "/my-service/**"
}
}
],
"filters": [
{
"name": "StripPrefix",
"args": {
"_genkey_1": "1"
}
}
]
}
]
}
}
}
}
3. 动态路由配置监听
创建一个配置类来监听 Nacos 配置变化,并刷新路由规则:
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.model.Properties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RoutesRefreshedEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import java.util.Properties as JavaProperties;
@Component
public class NacosDynamicRoute implements ApplicationRunner {
@Autowired
private RouteDefinitionRepository routeDefinitionRepository;
@Autowired
private ApplicationEventPublisher publisher;
private ConfigService configService;
public NacosDynamicRoute(NacosConfigProperties properties) throws NacosException {
JavaProperties javaProperties = new JavaProperties();
javaProperties.setProperty("serverAddr", properties.getServerAddr());
javaProperties.setProperty("namespace", properties.getNamespace());
configService = NacosFactory.createConfigService(javaProperties);
}
@Override
public void run(ApplicationArguments args) {
try {
String routeJson = configService.getConfig("gateway-routes.json", "DEFAULT_GROUP", 5000);
refreshRoutes(routeJson);
configService.addListener("gateway-routes.json", "DEFAULT_GROUP", s -> refreshRoutes(s));
} catch (NacosException e) {
e.printStackTrace();
}
}
private void refreshRoutes(String routeJson) {
SpringCloudRouteDefinition routeDefinition = JsonUtils.deserialize(routeJson, SpringCloudRouteDefinition.class);
routeDefinitionRepository.delete("*").subscribe();
routeDefinitionRepository.save(routeDefinition.getRouteDefinitions()).subscribe();
publisher.publishEvent(new RoutesRefreshedEvent(this));
}
// 内部类,用于反序列化 Nacos 配置
static class SpringCloudRouteDefinition {
private RouteDefinition[] routeDefinitions;
// getter 和 setter 省略
}
}
NacosDynamicRoute
类会在应用启动时从 Nacos 配置中心加载路由配置,并注册一个监听器来监听配置变化。当配置发生变化时,它会重新加载路由配置并刷新路由规则。点赞+关注,学习 Java 不迷路。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。