动态路由的核心需求:在不重启网关的情况下,实时修改路由规则。以下是 4 种实现方案:
方案 1:基于内存的动态路由(RefreshRoutesEvent)
适用场景:临时修改,重启失效
java
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
// 添加路由
public void addRoute(RouteDefinition definition) {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
publisher.publishEvent(new RefreshRoutesEvent(this)); // 触发刷新
}
// 删除路由
public void deleteRoute(String routeId) {
routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
publisher.publishEvent(new RefreshRoutesEvent(this));
}
缺点:路由数据不持久化
方案 2:数据库存储 + 定时轮询
实现步骤:
- 创建路由表:
sql
CREATE TABLE gateway_routes (
id VARCHAR(50) PRIMARY KEY,
uri VARCHAR(100),
predicates JSON,
filters JSON,
`order` INT
);
- 自定义
RouteDefinitionRepository
:
java
@Component
public class JdbcRouteDefinitionRepository implements RouteDefinitionRepository {
@Autowired
private RouteDao routeDao; // 自定义DAO
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return Flux.fromIterable(routeDao.findAll());
}
}
- 配置定时刷新(可选):
java
@Scheduled(fixedRate = 30000)
public void refreshRoutes() {
publisher.publishEvent(new RefreshRoutesEvent(this));
}
方案 3:Nacos 配置中心动态监听
实现步骤:
- 添加依赖:
XML
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 在Nacos创建配置(Data ID:
gateway-routes.json
):
XML
[{
"id": "user-service",
"predicates": [{"name": "Path", "args": {"pattern": "/user/**"}}],
"uri": "lb://user-service",
"filters": []
}]
3.配置监听:
java
@RefreshScope
@Configuration
public class NacosDynamicRoutes {
@Value("${spring.cloud.gateway.routes}")
private String routesConfig;
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
// 解析JSON配置构建路由
return builder.routes().build();
}
}
方案 4:Redis Pub/Sub 实时通知
实现步骤:
- 定义Redis消息监听:
java
@Component
public class RouteUpdateListener {
@Autowired
private ApplicationEventPublisher publisher;
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.addMessageListener((message, pattern) -> {
publisher.publishEvent(new RefreshRoutesEvent(this));
}, new ChannelTopic("gateway-routes-update"));
return container;
}
}
2.修改路由时发布消息:
java
redisTemplate.convertAndSend("gateway-routes-update", "refresh");
方案对比
方案 | 实时性 | 持久化 | 复杂度 | 适用场景 |
---|---|---|---|---|
内存刷新 | 高 | ❌ | 低 | 开发测试 |
数据库存储 | 中 | ✅ | 中 | 中小规模生产环境 |
Nacos配置中心 | 高 | ✅ | 中 | 阿里云体系 |
Redis Pub/Sub | 极高 | ✅ | 高 | 高并发分布式系统 |