spring cloud gateway 流程:

spring cloud gateway 官網(wǎng)的流程圖

具體執(zhí)行流程:
- DispatcherHandler :接收到請(qǐng)求后匹配 HandlerMapping ,此處會(huì)匹配到 RoutePredicateHandlerMapping ;
- RoutePredicateHandlerMapping :匹配 Route ;
- FilteringWebHandler :獲取 Route 的 GatewayFilter 列表,創(chuàng)建 GatewayFilterChain 來處理請(qǐng)求。
DispatcherHandler
請(qǐng)求分發(fā)處理器,是WebFlux的訪問入口??催@似曾相識(shí)的樣子,沒錯(cuò),對(duì)應(yīng)到Spring MVC中,跟它承擔(dān)類似作用的,就是DispatcherServlet。DispatcherHander也和DispatcherServlet的請(qǐng)求處理流程類似:

public class DispatcherHandler implements WebHandler, ApplicationContextAware {
private List<HandlerMapping> handlerMappings;
private List<HandlerAdapter> handlerAdapters;
private List<HandlerResultHandler> resultHandlers;
// 1. 初始化時(shí)從BeanFactory分別拉取類型為:HandlerMapping、HandlerAdapter、HandlerResultHandler
// 的所有Bean,填充到:handlerMappings、handlerAdapters、resultHandlers
protected void initStrategies(ApplicationContext context) {
Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerMapping.class, true, false);
ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
// 對(duì)所有的HandlerMapping排序,實(shí)現(xiàn)按優(yōu)先級(jí)選擇HandlerMapping使用的關(guān)鍵
// 因?yàn)镠andlerMapping的作用是判斷一個(gè)請(qǐng)求究竟適不適用于它所有對(duì)應(yīng)的Handler
// 最終是通過Handler去處理一個(gè)請(qǐng)求的,所以假設(shè)我們有一組HandlerMapping
// 這時(shí)來了個(gè)請(qǐng)求,我們就先把HandlerMapping按getOrder()拿到的優(yōu)先級(jí)排序
// 然后依次做HandlerMapping.getHandler(request);
// 如果這個(gè)過程是順序的,或者說同步的,那么第一次有某個(gè)HandlerMapping
// 拿到了Handler的話,說明它就是我們需要的Mr Right,方法可以直接返回這個(gè)了。
// 其實(shí)在Spring MVC里 DispatcherServlet就是通過 for if != null return
// 這樣去順序取HandlerMapping嘗試獲取Handler的。
// 但是在Spring WebFlux里,Reactor編程將這個(gè)過程異步化了:
// 通過concatMap()將所有的HandlerMapping異步getHandler(request);
// 它不保證每個(gè)HandlerMapping執(zhí)行g(shù)etHandler的順序,但保證最終得到的
// 一組結(jié)果,是按原先HandlerMapping的順序排好的,所以只用next()來獲取
// 第一個(gè)Handler,就得到了符合HandlerMapping優(yōu)先級(jí)的Handler,得到了
// 與同步執(zhí)行同樣的結(jié)果。假設(shè)HandlerMapping比較多,或者每個(gè)HandlerMapping
// 執(zhí)行g(shù)etHandler()的時(shí)間比較久,那么異步是有優(yōu)勢(shì)的,它相當(dāng)于是把這個(gè)過程
// 并行化了。但也并非一定總有優(yōu)勢(shì),要并行就需要分配多個(gè)線程去做任務(wù),也涉及到
// 最終結(jié)果的歸并。多個(gè)線程會(huì)占用額外的cpu資源,與其他任務(wù)競(jìng)爭(zhēng)時(shí)間片,CPU調(diào)度
// 線程造成上下文切換消耗也增加了。并且每個(gè)getHandler的線程計(jì)算結(jié)果是需要維護(hù)
// 對(duì)應(yīng)的優(yōu)先級(jí)的,因?yàn)樽罱K合并結(jié)果需要保持不改變順序。
AnnotationAwareOrderComparator.sort(mappings);
this.handlerMappings = Collections.unmodifiableList(mappings);
Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerAdapter.class, true, false);
this.handlerAdapters = new ArrayList<>(adapterBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerResultHandler.class, true, false);
this.resultHandlers = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(this.resultHandlers);
}
// 2.遍歷handlerMappings,獲取對(duì)應(yīng)的WebHandler
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
return Flux.fromIterable(this.handlerMappings)
// a.此處會(huì)匹配到RoutePredicateHandlerMapping
// b.RoutePredicateHandlerMapping匹配請(qǐng)求對(duì)應(yīng)的 Route
// c.返回FilteringWebHandler
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
.switchIfEmpty(createNotFoundError())
// d.執(zhí)行Handler
.flatMap(handler -> invokeHandler(exchange, handler))
// e.處理result
.flatMap(result -> handleResult(exchange, result));
}
// 3.執(zhí)行Handler,得到HandlerResult
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
if (this.handlerAdapters != null) {
for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
if (handlerAdapter.supports(handler)) {
return handlerAdapter.handle(exchange, handler);
}
}
}
return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}
// 5.處理返回結(jié)果
private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
return getResultHandler(result).handleResult(exchange, result)
.checkpoint("Handler " + result.getHandler() + " [DispatcherHandler]")
.onErrorResume(ex ->
result.applyExceptionHandler(ex).flatMap(exResult -> {
String text = "Exception handler " + exResult.getHandler() +
", error=\"" + ex.getMessage() + "\" [DispatcherHandler]";
return getResultHandler(exResult).handleResult(exchange, exResult).checkpoint(text);
}));
}
// 4.根據(jù)Result類型,獲取處理返回結(jié)果的Handler
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());
}
}
上面的dispatcherHandler的流程簡(jiǎn)單點(diǎn)說:先初始換那些handlerMapping、handlerAdater、resultAdater,從中遍歷了handlerMapping,最終它找到RoutePredicateHandlerMapping,就是開始第二步驟。
RoutePredicateHandlerMapping
- 通過路由定位器獲取全部路由(RouteLocator)
- 通過路由的謂語(Predicate)過濾掉不可用的路由信息
- 查找到路由信息后將路由信息設(shè)置當(dāng)上下文環(huán)境中(GATEWAY_ROUTE_ATTR)
- 返回gatway自定的webhandler(FilteringWebHandler)
執(zhí)行他的核心方法:
@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
// don't handle requests on management port if set and different than server port
if (this.managementPortType == DIFFERENT && this.managementPort != null
&& exchange.getRequest().getURI().getPort() == this.managementPort) {
return Mono.empty();
}
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());
return lookupRoute(exchange)
// .log("route-predicate-handler-mapping", Level.FINER) //name this
.flatMap((Function<Route, Mono<?>>) r -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isDebugEnabled()) {
logger.debug(
"Mapping [" + getExchangeDesc(exchange) + "] to " + r);
}
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
return Mono.just(webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isTraceEnabled()) {
logger.trace("No RouteDefinition found for ["
+ getExchangeDesc(exchange) + "]");
}
})));
}
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
return this.routeLocator.getRoutes()
// individually filter routes so that filterWhen error delaying is not a
// problem
.concatMap(route -> Mono.just(route).filterWhen(r -> {
// add the current route we are testing
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
return r.getPredicate().apply(exchange);
})
// instead of immediately stopping main flux due to error, log and
// swallow it
.doOnError(e -> logger.error(
"Error applying predicate for route: " + route.getId(),
e))
.onErrorResume(e -> Mono.empty()))
// .defaultIfEmpty() put a static Route not found
// or .switchIfEmpty()
// .switchIfEmpty(Mono.<Route>empty().log("noroute"))
.next()
// TODO: error handling
.map(route -> {
if (logger.isDebugEnabled()) {
logger.debug("Route matched: " + route.getId());
}
validateRoute(route, exchange);
return route;
});
/*
* TODO: trace logging if (logger.isTraceEnabled()) {
* logger.trace("RouteDefinition did not match: " + routeDefinition.getId()); }
*/
}
看lookupRoute方法就知道去找相應(yīng)的Route了,是根據(jù)routeId去找的。找到相應(yīng)的route,再返回FilteringWebHandler。
FilteringWebHandler 過濾web請(qǐng)求處理
她的本職工作是將GlobalFilter(全局過濾器)、GatewayFilter(一般來說是我們自己配置的,當(dāng)然也默認(rèn)內(nèi)置了一些,也內(nèi)含了自己在application配置文件中配的defaultFilter[如果有陪置的話]),放到同一個(gè)List里進(jìn)行優(yōu)先級(jí)排序,生成一個(gè)過濾器鏈。執(zhí)行過濾器鏈,就能順序執(zhí)行鏈中保存的所有Filter。
public class FilteringWebHandler implements WebHandler {
// 所有全局過濾器
private final List<GatewayFilter> globalFilters;
public FilteringWebHandler(List<GlobalFilter> globalFilters) {
// 1.初始化時(shí)加載所有全局過濾器,將他們適配為GatewayFilter類型,方便等會(huì)做合并
this.globalFilters = loadFilters(globalFilters);
}
// 適配器模式,通過兩次套娃把GlobalFilter封裝成GatewayFilter類型
private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
return filters.stream().map(filter -> {
// 2.Adapter持有GlobalFilter的引用
GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
if (filter instanceof Ordered) {
int order = ((Ordered) filter).getOrder();
// 3.OrderedGatewayFilter再持有一個(gè)Adapter
// 其實(shí)這里搞的挺無語的,那我直接返回Adapter又不是不能用,畢竟接口相同
// 說白了,還是跟職責(zé)隔離、設(shè)計(jì)解耦有關(guān)
// 就好比有時(shí)我們會(huì)糾結(jié)干嘛不直接把路由配置讀成Route是類似的
// 因?yàn)槲覀兊乃季S模式,就是快點(diǎn)達(dá)到目的,而忽略了擴(kuò)展性
// 假設(shè)現(xiàn)在我們需要有一個(gè)服務(wù)提供多個(gè)接口,包括了Filter接口的功能
// 那么,我們還是直接在Adapter上加接口,再持有一個(gè)跟它功能無關(guān)的工具人干活?
// 那職責(zé)就完全亂套了,我們大可以這樣:
// Kunkun implements ISing,IJump,IRap,IBasketball {
// private ISing singAdapter;
// private IJump jumpAdapter;
// private IRap rapAdapter;
// private IBasketball basketballAdapter;
// }
// 那么坤坤就會(huì)唱、跳、rap、籃球了
return new OrderedGatewayFilter(gatewayFilter, order);
}
return gatewayFilter;
}).collect(Collectors.toList());
}
public Mono<Void> handle(ServerWebExchange exchange) {
// 1.從exchange里拿到第二步匹配好的Route(匹配到后塞進(jìn)去的)
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
// 2.通過這個(gè)Route拿到它對(duì)應(yīng)的GatewayFilter列表
List<GatewayFilter> gatewayFilters = route.getFilters();
// 3.把前面已經(jīng)適配為GatewayFilter的全局過濾器拿過來,初始化一個(gè)總的過濾器列表
List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
// 4.然后把從Route里拿到的過濾器列表也塞進(jìn)去合并
combined.addAll(gatewayFilters);
// 5.對(duì)總的過濾器列表按優(yōu)先級(jí)排序
AnnotationAwareOrderComparator.sort(combined);
// 6.通過這個(gè)總的過濾器列表構(gòu)造一個(gè)過濾器鏈來執(zhí)行過濾邏輯
return new DefaultGatewayFilterChain(combined).filter(exchange);
}
所以總結(jié)就是將globalFilter和route的filters結(jié)合在一塊,形成一個(gè)過濾器鏈,之后請(qǐng)求就去逐個(gè)執(zhí)行過濾器鏈的過濾器。
參考文章: