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