Spring Cloud Gateway 基于 Nacos 的动态路由功能允许网关根据 Nacos 注册中心中的服务信息动态地进行路由配置,从而实现服务之间的动态调用和负载均衡。下面是一个简单的示例,演示了如何在 Spring Cloud Gateway 中使用 Nacos 作为注册中心,并实现动态路由的功能。
示例代码
-
首先,确保你的项目中已经添加了 Spring Cloud Gateway 和 Nacos 的依赖,并正确配置了 Nacos 注册中心的连接信息。
-
创建一个配置类,配置 Nacos 的动态路由功能。
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.util.pattern.PathPatternParser;
@Configuration
public class GatewayConfig {
@Bean
public RouteDefinitionLocator nacosRouteDefinitionLocator(DiscoveryClient discoveryClient, RouteDefinitionRepository routeDefinitionRepository) {
return new NacosRouteDefinitionLocator(discoveryClient, routeDefinitionRepository);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("app-route", r -> r.path("/app/**")
.uri("lb://APP-SERVICE"))
.build();
}
}
- 创建一个自定义的
NacosRouteDefinitionLocator
类,用于从 Nacos 中获取路由信息并实现动态路由。
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class NacosRouteDefinitionLocator implements RouteDefinitionLocator {
private final DiscoveryClient discoveryClient;
private final RouteDefinitionRepository routeDefinitionRepository;
public NacosRouteDefinitionLocator(DiscoveryClient discoveryClient, RouteDefinitionRepository routeDefinitionRepository) {
this.discoveryClient = discoveryClient;
this.routeDefinitionRepository = routeDefinitionRepository;
}
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return Flux.fromIterable(discoveryClient.getServices())
.flatMap(serviceId -> Flux.fromIterable(discoveryClient.getInstances(serviceId))
.map(instance -> {
RouteDefinition routeDefinition = new RouteDefinition();
routeDefinition.setId(serviceId + "-" + instance.getInstanceId());
routeDefinition.setUri("lb://" + serviceId);
routeDefinition.setPredicates(Arrays.asList(new PredicateDefinition("Path=/"+serviceId.toLowerCase()+"/**")));
return routeDefinition;
}));
}
}
- 在 application.yml 文件中配置 Nacos 的连接信息和网关的配置信息。
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: app-service
uri: lb://APP-SERVICE
predicates:
- Path=/app/**
server:
port: 8080
执行流程源码解析
NacosRouteDefinitionLocator
类实现了RouteDefinitionLocator
接口,其中的getRouteDefinitions
方法通过调用discoveryClient.getServices()
获取所有服务的名称,然后通过discoveryClient.getInstances(serviceId)
获取每个服务实例的信息,并根据这些信息构建路由定义对象RouteDefinition
。GatewayConfig
类中的nacosRouteDefinitionLocator
方法将NacosRouteDefinitionLocator
对象注入到 Spring 容器中,用于动态获取路由信息。GatewayConfig
类中的customRouteLocator
方法定义了一个自定义的路由规则,将/app/**
路径的请求转发到名为APP-SERVICE
的服务。- 最后,在
application.yml
文件中配置了 Nacos 的连接信息和路由规则。
通过以上步骤,Spring Cloud Gateway 就可以根据 Nacos 中注册的服务信息动态地进行路由配置,实现动态路由的功能。