路由改为动态刷新

This commit is contained in:
2025-08-22 22:32:29 +08:00
parent 5b443509ba
commit 5dae7f4ccb
3 changed files with 126 additions and 19 deletions

View File

@ -18,8 +18,8 @@ public class DynamicRouteScheduler {
@Autowired
private DiscoveryClient discoveryClient;
// 每30秒刷新一次路由可按需调整
@Scheduled(fixedRate = 30_000)
// 延迟5秒后开始执行避免与启动时的自动刷新冲突每30秒刷新一次路由可按需调整
@Scheduled(fixedRate = 30_000, initialDelay = 5_000)
public void refreshRoutes() {
log.info("refreshRoutes");
publisher.publishEvent(new RefreshRoutesEvent(this));

View File

@ -14,7 +14,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
@Configuration
//@Configuration
public class CustomRouteConfig {
@Autowired
private DiscoveryClient discoveryClient;
@ -27,21 +27,6 @@ public class CustomRouteConfig {
// .route("sczx-user", r -> r.path("/zc/user/**")
// .filters(f -> f.rewritePath("/zc/user/(?<segment>.*)", "/${segment}"))
// .uri(uriWithCustomLoadBalance("sczx-user")))
// .route("sczx-store", r -> r.path("/zc/store/**")
// .filters(f -> f.rewritePath("/zc/store/(?<segment>.*)", "/${segment}"))
// .uri(uriWithCustomLoadBalance("sczx-store")))
// .route("sczx-car", r -> r.path("/zc/car/**")
// .filters(f -> f.rewritePath("/zc/car/(?<segment>.*)", "/${segment}"))
// .uri(uriWithCustomLoadBalance("sczx-car")))
// .route("sczx-order", r -> r.path("/zc/order/**")
// .filters(f -> f.rewritePath("/zc/order/(?<segment>.*)", "/${segment}"))
// .uri(uriWithCustomLoadBalance("sczx-order")))
// .route("sczx-sync", r -> r.path("/zc/sync/**")
// .filters(f -> f.rewritePath("/zc/sync/(?<segment>.*)", "/${segment}"))
// .uri(uriWithCustomLoadBalance("sczx-sync")))
// .route("sczx-singlepay", r -> r.path("/zc/singlepay/**")
// .filters(f -> f.rewritePath("/zc/singlepay/(?<segment>.*)", "/${segment}"))
// .uri(uriWithCustomLoadBalance("sczx-singlepay")))
// .build();
//// .route("sczx_user", r -> r.path("/zc/user/**")
//// .uri("lb://sczx_user"))
@ -50,7 +35,7 @@ public class CustomRouteConfig {
//// .build();
// }
@Bean
// @Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
RouteLocatorBuilder.Builder routesBuilder = builder.routes();

View File

@ -0,0 +1,122 @@
package com.sczx.gateway.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import reactor.core.publisher.Flux;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
@Slf4j
@Configuration
public class DynamicRouteConfig implements RouteDefinitionLocator {
@Autowired
private DiscoveryClient discoveryClient;
private final AtomicInteger index = new AtomicInteger(0);
// 记录刷新次数
private final AtomicLong refreshCount = new AtomicLong(0);
// 记录上次刷新时间,用于防抖
private final AtomicReference<Long> lastRefreshTime = new AtomicReference<>(0L);
// 最小刷新间隔(毫秒)
private static final long MIN_REFRESH_INTERVAL = 3000;
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
long currentTime = System.currentTimeMillis();
long lastTime = lastRefreshTime.get();
// 防抖处理:如果距离上次刷新时间太短,则不处理
if (currentTime - lastTime < MIN_REFRESH_INTERVAL && refreshCount.get() > 0) {
log.info("刷新过于频繁,跳过本次刷新");
return Flux.empty();
}
lastRefreshTime.set(currentTime);
log.info("开始加载路由定义,第{}次调用", refreshCount.incrementAndGet());
List<RouteDefinition> routeDefinitions = new ArrayList<>();
// 定义需要路由的服务列表
String[] serviceNames = {"sczx-user", "sczx-store", "sczx-car", "sczx-order", "sczx-sync", "sczx-singlepay"};
// 为每个服务添加路由规则(如果服务存在)
for (String serviceName : serviceNames) {
if (hasServiceInstances(serviceName)) {
RouteDefinition routeDefinition = new RouteDefinition();
routeDefinition.setId(serviceName);
// 设置路径断言
routeDefinition.setPredicates(Collections.singletonList(
new PredicateDefinition("Path=/zc/" + serviceName.split("-")[1] + "/**")
));
// 设置过滤器
routeDefinition.setFilters(Collections.singletonList(
new org.springframework.cloud.gateway.filter.FilterDefinition(
"RewritePath=/zc/" + serviceName.split("-")[1] + "/(?<segment>.*), /$\\{segment}")
));
// 设置URI
routeDefinition.setUri(getServiceUri(serviceName));
routeDefinitions.add(routeDefinition);
} else {
log.warn("服务 {} 不存在实例,跳过路由配置", serviceName);
}
}
log.info("路由加载完成,共加载 {} 个路由定义", routeDefinitions.size());
return Flux.fromIterable(routeDefinitions);
}
/**
* 监听路由刷新事件
*/
@EventListener
public void onRefreshRoutes(RefreshRoutesEvent event) {
long count = refreshCount.get();
log.info("接收到路由刷新事件,当前为第{}次刷新", count);
}
/**
* 检查是否有可用的服务实例
*/
private boolean hasServiceInstances(String serviceName) {
List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
return instances != null && !instances.isEmpty();
}
/**
* 获取服务URI
*/
private URI getServiceUri(String serviceName) {
log.info("{} ,开始负载均衡路由", serviceName);
List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
if (instances == null || instances.isEmpty()) {
log.warn("No available instances for service: {}, returning default URI", serviceName);
return URI.create("http://localhost");
}
ServiceInstance selected = instances.get(Math.abs(index.getAndIncrement()) % instances.size());
log.info("Selected instance: {}", selected);
return URI.create("http://" + selected.getHost() + ":" + selected.getPort());
}
}