摘要:公司要做自己的網關,于是先把的過了一遍,然后把源碼在看了一遍,這樣公司的需求就搞定了。包括動態路由,多緯度限流,記錄請求參數及返回參數也可修改。至此,流程就走完了。
公司要做自己的網關,于是先把github的issue過了一遍,然后把gateway源碼在看了一遍,這樣公司的需求就搞定了。包括動態路由,多緯度限流,記錄請求參數及返回參數(也可修改)。先從請求進入網關說起吧:
請求先進入HttpWebHandlerAdapter 類里
@Override public Monohandle(ServerHttpRequest request, ServerHttpResponse response) { ServerWebExchange exchange = createExchange(request, response); //getDelegate()獲取的是ExceptionHandlingWebHandler,用來處理全局的異常 return getDelegate().handle(exchange) .onErrorResume(ex -> handleFailure(request, response, ex)) .then(Mono.defer(response::setComplete)); } protected ServerWebExchange createExchange(ServerHttpRequest request, ServerHttpResponse response) { //這里的DefaultServerWebExchange就是后面過濾器用到的ServerWebExchange,包括封裝的請求參數,以及再執行過濾器時往里面添加參數,參數是線程安全的 return new DefaultServerWebExchange(request, response, this.sessionManager, getCodecConfigurer(), getLocaleContextResolver(), this.applicationContext); }
往下走:
前面的getDelegate().handle(exchange)進入DefaultWebFilterChain類里 public class DefaultWebFilterChain implements WebFilterChain { private final Listfilters; private final WebHandler handler; private final int index; ······· @Override public Mono filter(ServerWebExchange exchange) { return Mono.defer(() -> { if (this.index < this.filters.size()) {//先執行完所有的 WebFilter WebFilter filter = this.filters.get(this.index); //這里重新new DefaultWebFilterChain然后調用filter方法,也就會順序執行所有的過濾器了 WebFilterChain chain = new DefaultWebFilterChain(this, this.index + 1); return filter.filter(exchange, chain); } else {//然后才會執行網關自定義的過濾器 return this.handler.handle(exchange); } }); } }
往下:
this.handler.handle(exchange),進入到DispatcherHandler類里 public class DispatcherHandler implements WebHandler, ApplicationContextAware { ···· @Nullable //HandlerMapping用來判斷請求進來的地址應該怎么處理,可能會匹配到spring webflux的HandlerFunction, 或者是controller,然后才是我們在網關配置的路由,都匹配不上的話就到SimpleUrlHandlerMapping來處理404 了,這里其實有點不太明白為什么作者會把網關路由的優先級設置低于HandlerFunction,controller,網關畢竟是 用來轉發,所以我另外加了個類設置了最高的優先級(修改RoutePredicateHandlerMapping中的order) private ListhandlerMappings; @Nullable private List handlerAdapters; @Nullable //處理網關調用第三方服務返回的結果 private List resultHandlers; ····· public DispatcherHandler(ApplicationContext applicationContext) { initStrategies(applicationContext); } @Override public void setApplicationContext(ApplicationContext applicationContext) { initStrategies(applicationContext); } //網關啟動時調用,設置三個list變量并排序 protected void initStrategies(ApplicationContext context) { Map mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( context, HandlerMapping.class, true, false); ArrayList mappings = new ArrayList<>(mappingBeans.values()); AnnotationAwareOrderComparator.sort(mappings); this.handlerMappings = Collections.unmodifiableList(mappings); Map adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( context, HandlerAdapter.class, true, false); this.handlerAdapters = new ArrayList<>(adapterBeans.values()); AnnotationAwareOrderComparator.sort(this.handlerAdapters); Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( context, HandlerResultHandler.class, true, false); this.resultHandlers = new ArrayList<>(beans.values()); AnnotationAwareOrderComparator.sort(this.resultHandlers); } @Override public Mono handle(ServerWebExchange exchange) { if (logger.isDebugEnabled()) { ServerHttpRequest request = exchange.getRequest(); logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]"); } if (this.handlerMappings == null) { return Mono.error(HANDLER_NOT_FOUND_EXCEPTION); } return Flux.fromIterable(this.handlerMappings) //handlerMappings根據路由匹配合適的handler,確定是網關處理還是代理到第三方 .concatMap(mapping -> mapping.getHandler(exchange)) //上面的匹配可能會出現多個符合條件的,next()的作用在于匹配到第一個就停止匹配 .next() .switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION)) .flatMap(handler -> invokeHandler(exchange, handler)) .flatMap(result -> handleResult(exchange, result)); } private Mono invokeHandler(ServerWebExchange exchange, Object handler) { if (this.handlerAdapters != null) { for (HandlerAdapter handlerAdapter : this.handlerAdapters) { if (handlerAdapter.supports(handler)) {//前面匹配到handler后,循環便利是否支持并執行 hadler方法 return handlerAdapter.handle(exchange, handler); } } } return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler)); } private Mono handleResult(ServerWebExchange exchange, HandlerResult result) { return getResultHandler(result).handleResult(exchange, result) .onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult -> //同樣是循環遍歷是否支持并執行 handleResult方法 getResultHandler(exceptionResult).handleResult(exchange, exceptionResult))); } private HandlerResultHandler getResultHandler(HandlerResult handlerResult) { if (this.resultHandlers != null) { for (HandlerResultHandler resultHandler : this.resultHandlers) { if (resultHandler.supports(handlerResult)) { return resultHandler; } } } throw new IllegalStateException("No HandlerResultHandler for " + handlerResult.getReturnValue()); } }
接上面 :
handlerAdapter.handle(exchange, handler); 只說匹配到我們配置的路由的情況 進入到SimpleHandlerAdapter類 public class SimpleHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { return WebHandler.class.isAssignableFrom(handler.getClass()); } @Override public Monohandle(ServerWebExchange exchange, Object handler) { WebHandler webHandler = (WebHandler) handler; //根據傳進來的不同handler處理不同的情況,匹配上路由的話傳進來的是FilteringWebHandler Mono mono = webHandler.handle(exchange); return mono.then(Mono.empty()); } } 繼續看FilteringWebHandler類: public class FilteringWebHandler implements WebHandler { protected static final Log logger = LogFactory.getLog(FilteringWebHandler.class); private final List globalFilters; //在GatewayAutoConfiguration中配置bean,注入所有實現GlobalFilter的類 public FilteringWebHandler(List globalFilters) { this.globalFilters = loadFilters(globalFilters); } //將GlobalFilter和GatewayFilter合并并排序 private static List loadFilters(List filters) { return filters.stream() .map(filter -> { GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter); if (filter instanceof Ordered) { int order = ((Ordered) filter).getOrder(); return new OrderedGatewayFilter(gatewayFilter, order); } return gatewayFilter; }).collect(Collectors.toList()); } /* TODO: relocate @EventListener(RefreshRoutesEvent.class) void handleRefresh() { this.combinedFiltersForRoute.clear(); }*/ @Override public Mono handle(ServerWebExchange exchange) { //獲取前面在匹配路由時放進ServerWebExchange中的路由數據 Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR); //獲取本路由配置的過濾器 List gatewayFilters = route.getFilters(); List combined = new ArrayList<>(this.globalFilters); //把當前路由的過濾器跟全局過濾器組合 combined.addAll(gatewayFilters); //排序 AnnotationAwareOrderComparator.sort(combined); if (logger.isDebugEnabled()) { logger.debug("Sorted gatewayFilterFactories: "+ combined); } return new DefaultGatewayFilterChain(combined).filter(exchange); } private static class DefaultGatewayFilterChain implements GatewayFilterChain { private final int index; private final List filters; public DefaultGatewayFilterChain(List filters) { this.filters = filters; this.index = 0; } private DefaultGatewayFilterChain(DefaultGatewayFilterChain parent, int index) { this.filters = parent.getFilters(); this.index = index; } public List getFilters() { return filters; } @Override public Mono filter(ServerWebExchange exchange) { return Mono.defer(() -> { if (this.index < filters.size()) { //與之前的WebFilter 一樣,每次執行都new DefaultGatewayFilterChain調用filter方法, //不斷往下執行直到過濾器走完 GatewayFilter filter = filters.get(this.index); DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this, this.index + 1); return filter.filter(exchange, chain); } else { return Mono.empty(); // complete } }); } } private static class GatewayFilterAdapter implements GatewayFilter { private final GlobalFilter delegate; public GatewayFilterAdapter(GlobalFilter delegate) { this.delegate = delegate; } @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { return this.delegate.filter(exchange, chain); } @Override public String toString() { final StringBuilder sb = new StringBuilder("GatewayFilterAdapter{"); sb.append("delegate=").append(delegate); sb.append("}"); return sb.toString(); } } }
然后,在排序倒數第二的過濾器NettyRoutingFilter中,調用默認的HttpClient,代理到后面的服務。
至此,流程就走完了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77400.html
摘要:將請求封裝成將請求封裝成的接口定義是但是最外層傳進來的參數是和,需要將他們封裝成,這個工作就是在中做的。其實主要任務就是將各種參數封裝成除了和本次請求相關的和,還有會話管理器,編碼解碼器配置,國際化配置還有用于擴展。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent接下來,將進入我們升級之路的又一大模塊,即網關模塊。網關模塊我們廢棄了...
摘要:現在項目大多開始前后端分離,前端開發的時候可以用的來配置線上打包的話可以直接放到后臺項目的靜態資源目錄了,這樣就不會有跨域問題,或者放到里在配置好資源目錄就行,這些方案網上都有就不展開了,現在說說怎么處理跨域我們看類里的方法根據獲取不同的后 現在項目大多開始前后端分離,前端開發的時候可以用webpack的proxytable來配置線上打包的話可以直接放到后臺項目的靜態資源目錄了,這樣就...
摘要:以流量為切入點,從流量控制熔斷降級系統負載保護等多個維度保護服務的穩定性分布式系統的流量防衛兵。歡迎關注我們獲得更多的好玩實踐 之前分享過 一篇 《Spring Cloud Gateway 原生的接口限流該怎么玩》, 核心是依賴Spring Cloud Gateway 默認提供的限流過濾器來實現 原生RequestRateLimiter 的不足 配置方式 spring: clou...
摘要:以流量為切入點,從流量控制熔斷降級系統負載保護等多個維度保護服務的穩定性分布式系統的流量防衛兵。歡迎關注我們獲得更多的好玩實踐 之前分享過 一篇 《Spring Cloud Gateway 原生的接口限流該怎么玩》, 核心是依賴Spring Cloud Gateway 默認提供的限流過濾器來實現 原生RequestRateLimiter 的不足 配置方式 spring: clou...
閱讀 2434·2021-11-23 09:51
閱讀 2463·2021-11-11 17:21
閱讀 3105·2021-09-04 16:45
閱讀 2387·2021-08-09 13:42
閱讀 2224·2019-08-29 18:39
閱讀 2891·2019-08-29 14:12
閱讀 1294·2019-08-29 13:49
閱讀 3368·2019-08-29 11:17