需求描述
標準網關動態路由功能是重要的一環,將路由、斷言以及過濾器信息,持久化到 Mysql 中,通過配置后臺頁面實現路由、斷言、以及過濾器等配置的增刪改查。
Spring Cloud Gateway 路由及黑白名單實現背景 Spring Cloud 路由API
Spring Cloud Gateway 通過定義 RouteDefinitionRepository 來實現動態路由.
//保存路由緩存 public interface RouteDefinitionWriter { Mono<Void> save(Mono<RouteDefinition> route); Mono<Void> delete(Mono<String> routeId); }
//獲取路由緩存 public interface RouteDefinitionLocator { Flux<RouteDefinition> getRouteDefinitions(); }
Spring Cloud 配置文件路由加載方式
public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator { private final GatewayProperties properties; public PropertiesRouteDefinitionLocator(GatewayProperties properties) { this.properties = properties; } @Override public Flux<RouteDefinition> getRouteDefinitions() { return Flux.fromIterable(this.properties.getRoutes()); } }
Spring Cloud 黑白名 FilterFactory
利用 Spring Cloud Gateway 聲明的一個工廠接口 GatewayFilterFactory, 定義 黑白名單過濾器
BlacklistGatewayFilterFactory 類圖
WhitelistGatewayFilterFactory 類圖
動態路由設計 Spring Cloud Gateway 路由實體類
Spring Cloud Gateway 通過定義 RouteDefinition 類裝載路由信息。
package org.springframework.cloud.gateway.route; public class RouteDefinition { //路由 ID @NotEmpty private String id = UUID.randomUUID().toString(); //斷言數組 @NotEmpty @Valid private List<PredicateDefinition> predicates = new ArrayList<>(); //過濾器數組 @Valid private List<FilterDefinition> filters = new ArrayList<>(); // 路由地址 @NotNull private URI uri; // 路由順序 private int order = 0; }
數據庫設計
路由表
drop table if exists gateway_route_t; create table if not exists gateway_route_t ( ID int auto_increment primary key, ROUTE_ID varchar(255) not null comment "路由ID", ROUTE_ORDER int default 0 null comment "路由順序", URI varchar(255) not null comment "路由路徑", VALID int default 1 not null comment "是否有效:0-無效,1-有效", CREATE_USER varchar(200) null comment "創建人", CREATE_TIME datetime null comment "創建時間", UPDATE_USER varchar(200) null comment "修改人", UPDATE_TIME datetime null comment "修改時間", constraint idx_ROUTE_ID_index unique (ROUTE_ID) ) comment "網關路由信息表" charset = utf8;
路由參數表
drop table if exists gateway_route_param_t; create table if not exists gateway_route_param_t ( ID int auto_increment primary key, ROUTE_ID varchar(255) not null comment "路由ID", PARAM_NAME varchar(255) not null comment "參數name", PARAM_KEY varchar(255) not null comment "參數 key", PARAM_VALUE varchar(255) not null comment "參數 value", TYPE int not null comment "參數類型,1為 predicate,2為過 filter", VALID int default 1 not null comment "是否有效:0-無效,1-有效", CREATE_USER varchar(200) null comment "創建人", CREATE_TIME datetime null comment "創建時間", UPDATE_USER varchar(200) null comment "修改人", UPDATE_TIME datetime null comment "修改時間" ) comment "網關路由參數表" charset = utf8; create index idx_route_id on gateway_route_param_t (ROUTE_ID);
接口設計 接口定義
路由表配置接口
封裝 gateway_route_t dao 層接口.
/** * <功能描述> 路由表接口 * * @author 20024322 * @date 2020/12/24 13:20 */ public interface IRouteConfigService extends IService<RouteDomain>
路由參數表配置接口
封裝 gateway_route_param_t dao 層接口.
/** * <功能描述> 路由參數表接口 * * @author 20024322 * @date 2020/12/24 13:20 */ public interface IRouteParamConfigService extends IService<RouteParamDomain>
數據庫路由服務接口
封裝 路由表配置服務接口以及路由參數表配置接口, 對外層提供對數據庫路由信息的操作.
/** * <功能描述> 數據庫路由服務 * * @author 20024322 * @date 2020/12/24 13:20 */ public interface IRoutePropertiesService
網關路由緩存接口
封裝 RouteDefinitionRepository 接口,對外提供對網關路由緩存的刷新.
/** * <功能描述> 網關緩存路由服務 * * @author 20024322 * @date 2020/12/24 13:20 */ public interface IGatewayRouteService extends ApplicationEventPublisherAware
路由事件監聽接口
配置需要監聽路由變化的 service 實現
/** * <功能描述> 路由事件監聽接口 * * @author 20024322 * @date 2020/12/24 13:20 */ public interface RouteEventListener extends ApplicationListener<RefreshCacheEvent>
數據庫黑白名單配置接口
/** * <功能描述> API Filter 接口定義 * * @author 20024322 * @date 2020/12/24 13:20 */ public interface IApiFilterService
網關白名單緩存接口
提供指定路由 API 白名單check 監聽路由事件
/** * <功能描述> API 白名單緩存接口 * * @author 20024322 * @date 2020/12/24 13:20 */ public interface IApiCacheService extends RouteEventListener
路由參數執行校驗接口
封裝 提供路由參數的校驗的接口.
/** * <功能描述> 路由參數校驗 * * @author 20024322 * @date 2020/12/24 13:20 */ public interface IRouteValidateExecutorService
接口類圖 路由及黑白名單類圖
斷言及過濾器封裝類圖
集群緩存刷新事件處理策略類圖
路由初始化設計 重載 PropertiesRouteDefinitionLocator
/** * <功能描述> 重寫 PropertiesRouteDefinitionLocator bean * 將配置文件中的路由信息通過 MysqlRouteConfig 載入。 * * @author 20024322 * @date 2020/12/24 13:20 */ @Configuration @AutoConfigureBefore({MysqlRouteConfig.class}) public class PropertiesRouteConfig { @Bean public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator( GatewayProperties properties) { return new PropertiesRouteDefinitionLocator(new GatewayProperties()); } }
定義 initMysqlRouteDefinition Bean 加載數據庫及配置文件的路由配置
/** * <功能描述> 從Mysql中初始化路由信息 * 覆蓋配置文件中的路由信息 * * @author 20024322 * @date 2020/12/24 13:20 */ @Configuration public class MysqlRouteConfig { private final IRoutePropertiesService routePropertiesService; private final IGatewayRouteService gatewayRouteService; public MysqlRouteConfig(IRoutePropertiesService routePropertiesService, IGatewayRouteService gatewayRouteService) { this.routePropertiesService = routePropertiesService; this.gatewayRouteService = gatewayRouteService; } /** * 初始化 gatewayProperties 中的 route * * @param gatewayProperties * @return */ @Bean public List<RouteDefinition> initMysqlRouteDefinition(GatewayProperties gatewayProperties) { List<RouteDefinition> gatewayPropertiesRoutes = gatewayProperties.getRoutes(); //初始化數據庫路由信息 List<RouteDefinition> routeDefinitionList = routePropertiesService.getRouteDefinitionList(); if (CollectionUtils.isEmpty(gatewayProperties.getRoutes()) && CollectionUtils.isEmpty(routeDefinitionList)) { throw new BizBaseException(HprmcExceptionCode.ROUTE_NOT_FOUND); } Set<String> routeIds = routeDefinitionList.stream() .map(RouteDefinition::getId).collect(Collectors.toSet()); if (gatewayPropertiesRoutes.stream().anyMatch(r -> routeIds.contains(r.getId()))) { throw new BizBaseException(HprmcExceptionCode.ROUTE_INIT_CONFLICT); } //將配置文件中的路由信息添加到 InMemoryRouteDefinitionRepository 成員變量中 if (!CollectionUtils.isEmpty(gatewayPropertiesRoutes)) { gatewayPropertiesRoutes.forEach(gatewayRouteService::addInMemoryRouteRefresh); } //寫到 InMemoryRouteDefinitionRepository 成員初始化緩存 if (!CollectionUtils.isEmpty(routeDefinitionList)) { routeDefinitionList.forEach(gatewayRouteService::addInMemoryRouteRefresh); } return routeDefinitionList; } }
到此這篇關于SpringCloud Gateway 利用 Mysql 實現動態路由的方法的文章就介紹到這了,更多相關SpringCloud Gateway 實現動態路由內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://juejin.cn/post/6928933330029117448