摘要:先看看是怎么獲取我們配置的路由在啟動時,幫我們注冊了一系列這里注入所有,我們在配置文件里配置的路由就是通過子類來完成的,可以參考實現(xiàn)自己的的存儲,會在后面轉換成接著看類里的獲取路由定義方法即輪訓所有的市現(xiàn)率調用,這樣就把所有整合到一起了接著
先看看gateway是怎么獲取我們配置的路由:
在gateway啟動時,GatewayAutoConfiguration幫我們注冊了一系列beans
@Bean @Primary public RouteDefinitionLocator routeDefinitionLocator(ListrouteDefinitionLocators) { //這里注入所有RouteDefinitionLocator,我們在配置文件里配置的路由就是通過子類PropertiesRouteDefinitionLocator來完成的, //可以參考InMemoryRouteDefinitionRepository實現(xiàn)自己的RouteDefinition的存儲,RouteDefinition會在后面轉換成Route return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators)); } //接著看CompositeRouteDefinitionLocator類里的獲取路由定義方法: public Flux getRouteDefinitions() { //即輪訓所有RouteDefinitionLocator的市現(xiàn)率調用getRouteDefinitions,這樣就把所有RouteDefinition整合到一起了 return this.delegates.flatMap(RouteDefinitionLocator::getRouteDefinitions); } //接著看GatewayAutoConfiguration,剛才的bean RouteDefinitionLocator 作為參數(shù)注入到routeDefinitionLocator @Bean public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, List GatewayFilters, List predicates, RouteDefinitionLocator routeDefinitionLocator) { return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties); } //看RouteDefinitionRouteLocator類: public class RouteDefinitionRouteLocator implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware { ······ public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator, List predicates, List gatewayFilterFactories, GatewayProperties gatewayProperties) { this.routeDefinitionLocator = routeDefinitionLocator; //RoutePredicateFactory放到map里,去掉RoutePredicateFactory后綴,所以配置時就可以寫成 //predicates: // - Path=/abc/* //的形式而不用寫完整的PathRoutePredicateFactory initFactories(predicates); //把bean名字里的GatewayFilterFactory去掉,所以我們配置文件里配置時也要把GatewayFilterFactory去掉,不然會找不到 gatewayFilterFactories.forEach(factory -> this.gatewayFilterFactories.put(factory.name(), factory)); this.gatewayProperties = gatewayProperties; } ······ @Override public Flux getRoutes() { return this.routeDefinitionLocator.getRouteDefinitions() .map(this::convertToRoute)//獲取所有的RouteDefinition后轉為Route //TODO: error handling .map(route -> { if (logger.isDebugEnabled()) { logger.debug("RouteDefinition matched: " + route.getId()); } return route; }); } private Route convertToRoute(RouteDefinition routeDefinition) { //獲取所有匹配規(guī)則,所有的規(guī)則都滿足才走對應Route AsyncPredicate predicate = combinePredicates(routeDefinition); //獲取全部過濾器 List gatewayFilters = getFilters(routeDefinition); return Route.async(routeDefinition) .asyncPredicate(predicate) .replaceFilters(gatewayFilters) .build(); } private List getFilters(RouteDefinition routeDefinition) { List filters = new ArrayList<>(); //把全局過濾器添加到當前路由,loadGatewayFilters調用GatewayFilterFactory里的apply配置類里面的靜態(tài)Config類,并且把沒實現(xiàn)Ordered接口的類用OrderedGatewayFilter代理一下,方便下面排序 if (!this.gatewayProperties.getDefaultFilters().isEmpty()) { filters.addAll(loadGatewayFilters("defaultFilters", this.gatewayProperties.getDefaultFilters())); } //添加本條路由定義的過濾器 if (!routeDefinition.getFilters().isEmpty()) { filters.addAll(loadGatewayFilters(routeDefinition.getId(), routeDefinition.getFilters())); } //排序 AnnotationAwareOrderComparator.sort(filters); return filters; } private AsyncPredicate combinePredicates(RouteDefinition routeDefinition) { //獲取路由的判斷條件,比如我們大多是根據(jù)url判斷,用的是PathRoutePredicateFactory List predicates = routeDefinition.getPredicates(); AsyncPredicate predicate = lookup(routeDefinition, predicates.get(0)); for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) { AsyncPredicate found = lookup(routeDefinition, andPredicate); predicate = predicate.and(found);//如果有多個匹配規(guī)則就要滿足所有的才可以 } //返回的結果會在RoutePredicateHandlerMapping類里使用apply方法調用 return predicate; } @SuppressWarnings("unchecked") private AsyncPredicate lookup(RouteDefinition route, PredicateDefinition predicate) { RoutePredicateFactory
說了那么多終于把網關匹配路由的流程說完了,如果上面都看明白的話,動態(tài)路由就好辦了
網關已經把InMemoryRouteDefinitionRepository注冊成bean(也可以參考這個類自己實現(xiàn)RouteDefinitionRepository接口),我們把它當作個service注入到controller,
前端把RouteDefinition用json的格式post過來,我們調用InMemoryRouteDefinitionRepository的save或者delete方法,再用spring的事件觸發(fā)RefreshRoutesEvent事件來刷新路由就行了,等下次請求的時候就可以拿到新的路由配置了
順序是:
1.RoutePredicateHandlerMapping 的lookupRoute方法,由于路由刷新事件把路由緩存清了,所以重新獲取
2.CompositeRouteLocator 的getRoutes方法遍歷所有RouteLocator實現(xiàn)類的getRoutes方法
3.RouteDefinitionRouteLocator 的getRoutes方法里重新獲取了所有的路由定義,也就把我們剛剛用事件添加的路由也獲取了
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77399.html
摘要:以流量為切入點,從流量控制熔斷降級系統(tǒng)負載保護等多個維度保護服務的穩(wěn)定性分布式系統(tǒng)的流量防衛(wèi)兵。歡迎關注我們獲得更多的好玩實踐 之前分享過 一篇 《Spring Cloud Gateway 原生的接口限流該怎么玩》, 核心是依賴Spring Cloud Gateway 默認提供的限流過濾器來實現(xiàn) 原生RequestRateLimiter 的不足 配置方式 spring: clou...
摘要:以流量為切入點,從流量控制熔斷降級系統(tǒng)負載保護等多個維度保護服務的穩(wěn)定性分布式系統(tǒng)的流量防衛(wèi)兵。歡迎關注我們獲得更多的好玩實踐 之前分享過 一篇 《Spring Cloud Gateway 原生的接口限流該怎么玩》, 核心是依賴Spring Cloud Gateway 默認提供的限流過濾器來實現(xiàn) 原生RequestRateLimiter 的不足 配置方式 spring: clou...
摘要:公司要做自己的網關,于是先把的過了一遍,然后把源碼在看了一遍,這樣公司的需求就搞定了。包括動態(tài)路由,多緯度限流,記錄請求參數(shù)及返回參數(shù)也可修改。至此,流程就走完了。 公司要做自己的網關,于是先把github的issue過了一遍,然后把gateway源碼在看了一遍,這樣公司的需求就搞定了。包括動態(tài)路由,多緯度限流,記錄請求參數(shù)及返回參數(shù)(也可修改)。先從請求進入網關說起吧: 請求先進...
摘要:灰度發(fā)布是指在黑與白之間,能夠平滑過渡的一種發(fā)布方式。如何使用進行灰度發(fā)布呢將分一下四步第一,設置網關權重路由設置中提供了去實現(xiàn)根據(jù)分組設置權重進行路由,因此使用起來相對比較簡單,有興趣的可以閱讀源碼。 灰度發(fā)布是指在黑與白之間,能夠平滑過渡的一種發(fā)布方式。在其上可以進行A/B testing,即讓一部分用戶繼續(xù)用產品特性A,一部分用戶開始用產品特性B,如果用戶對B沒有什么反對意見,那...
閱讀 1329·2021-11-15 11:37
閱讀 2214·2021-09-23 11:21
閱讀 1300·2019-08-30 15:55
閱讀 2105·2019-08-30 15:55
閱讀 2815·2019-08-30 15:52
閱讀 2819·2019-08-30 11:12
閱讀 1573·2019-08-29 18:45
閱讀 1885·2019-08-29 14:04