歡迎大家關注我的微信公眾號【老周聊架構】,Java后端主流技術堆疊的原理、原始碼分析、架構以及各種互聯網高并發、高性能、高可用的解決方案,
一、前言
前幾篇我們講了 Gateway 相應的初始化、路由相關模型以及 Predicate 謂詞詳解,這一篇我們再來講一下 Filter Chain 過濾器鏈,講完這一篇,相信你對 Gateway 原始碼整體設計思想有個深刻的體會了,后續你想去摳細節也不是什么難事了,前幾篇可以回顧下:
Spring Cloud Gateway 原始碼剖析之配置初始化
Spring Cloud Gateway 原始碼剖析之Route資料模型
Spring Cloud Gateway 原始碼剖析之Predicate謂詞詳解
回顧完了我們再來看一張 Spring Cloud Gateway 的整體流程圖,相信一直看完這個系列的很快的就能知道上一篇我們講到了 Predicate 斷言這一塊,如果 Handler Mapping 匹配成功則會通過 GatewayWebHandler 創建請求對應的 Route 對應的 Filter Chain 來進行處理請求,我們按照這個流程圖來看的話,接下來要講的是通過網關自定義的 WebHandler 來處理請求,這里就來講一下最重要 FilteringWebHandler 過濾器鏈,

二、FilteringWebHandler
// org.springframework.cloud.gateway.handler.FilteringWebHandler
/**
* 通過過濾器處理web請求的處理器
*/
public class FilteringWebHandler implements WebHandler {
protected static final Log logger = LogFactory.getLog(FilteringWebHandler.class);
/**
* 全域過濾器
*/
private final List<GatewayFilter> globalFilters;
public FilteringWebHandler(List<GlobalFilter> globalFilters) {
this.globalFilters = loadFilters(globalFilters);
}
/**
* 組成過濾鏈
* 包裝加載全域的過濾器,將全域過濾器包裝成GatewayFilter
*/
private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
return (List)filters.stream().map((filter) -> {
FilteringWebHandler.GatewayFilterAdapter gatewayFilter = new FilteringWebHandler.GatewayFilterAdapter(filter);
// 當 GlobalFilter 子類實作了 org.springframework.core.Ordered 介面,在委托一層 OrderedGatewayFilter ,
// 這樣 AnnotationAwareOrderComparator#sort(List) 方法好排序,
if (filter instanceof Ordered) {
int order = ((Ordered)filter).getOrder();
return new OrderedGatewayFilter(gatewayFilter, order);
} else {
return gatewayFilter;
}
}).collect(Collectors.toList());
}
// 按照過濾鏈的順序依次執行
public Mono<Void> handle(ServerWebExchange exchange) {
// 獲取請求背景關系設定的路由實體
Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
// 獲取路由定義下的網關過濾器集合
List<GatewayFilter> gatewayFilters = route.getFilters();
// 組合全域的過濾器與路由配置的過濾器
List<GatewayFilter> combined = new ArrayList(this.globalFilters);
// 添加路由配置過濾器到集合尾部
combined.addAll(gatewayFilters);
// 對過濾器進行排序
AnnotationAwareOrderComparator.sort(combined);
if (logger.isDebugEnabled()) {
logger.debug("Sorted gatewayFilterFactories: " + combined);
}
// 創建過濾器鏈表對其進行鏈式呼叫
return (new FilteringWebHandler.DefaultGatewayFilterChain(combined)).filter(exchange);
}
...
}
FilteringWebHandler 的執行順序:
- 構建一個包含全域過濾器的集合(combined)
- 獲取背景關系中的路由資訊 GATEWAY_ROUTE_ATTR
- 將路由里的過濾器添加到集合中(combined)
- 對過濾器集合進行排序操作
- 通過過濾器集合組裝過濾器鏈表,并進行呼叫(DefaultGatewayFilterChain 與 Servlet 中的 FilterChain 的原理是一致的)
- 通過過濾器來處理請求到具體業務服務
2.1 GatewayFilter 與 GlobalFilter 的關系
private final List<GatewayFilter> globalFilters;
public FilteringWebHandler(List<GlobalFilter> globalFilters) {
this.globalFilters = loadFilters(globalFilters);
}
2.1.1 GatewayFilter 網關過濾器介面
public interface GatewayFilter extends ShortcutConfigurable {
String NAME_KEY = "name";
String VALUE_KEY = "value";
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
GatewayFilter 有三種型別的子類實作
-
OrderedGatewayFilter :有序的網關過濾器實作類,在 FilterChain 里,過濾器陣列首先會按照 order 升序排序,按照順序過濾請求,
public class OrderedGatewayFilter implements GatewayFilter, Ordered { // 委托的 GatewayFilter private final GatewayFilter delegate; // order代表順序 private final int order; public OrderedGatewayFilter(GatewayFilter delegate, int order) { this.delegate = delegate; this.order = order; } public GatewayFilter getDelegate() { return this.delegate; } public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return this.delegate.filter(exchange, chain); } public int getOrder() { return this.order; } public String toString() { StringBuilder sb = new StringBuilder("OrderedGatewayFilter{"); sb.append("delegate=").append(this.delegate); sb.append(", order=").append(this.order); sb.append('}'); return sb.toString(); } } -
GatewayFilterAdapter:網關過濾器配接器,在 GatewayFilterChain 使用 GatewayFilter 過濾請求,所以通過 GatewayFilterAdapter 將 GlobalFilter 適配成 GatewayFilter,
private static class GatewayFilterAdapter implements GatewayFilter { // 委托的 GlobalFilter private final GlobalFilter delegate; public GatewayFilterAdapter(GlobalFilter delegate) { this.delegate = delegate; } public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return this.delegate.filter(exchange, chain); } public String toString() { StringBuilder sb = new StringBuilder("GatewayFilterAdapter{"); sb.append("delegate=").append(this.delegate); sb.append('}'); return sb.toString(); } } -
ModifyResponseGatewayFilter:用于修改 Response
public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered { private final ModifyResponseBodyGatewayFilterFactory.Config config; public ModifyResponseGatewayFilter(ModifyResponseBodyGatewayFilterFactory.Config config) { this.config = config; } public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) { public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { Class inClass = ModifyResponseGatewayFilter.this.config.getInClass(); Class outClass = ModifyResponseGatewayFilter.this.config.getOutClass(); String originalResponseContentType = (String)exchange.getAttribute("original_response_content_type"); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add("Content-Type", originalResponseContentType); ModifyResponseBodyGatewayFilterFactory.ResponseAdapter responseAdapter = ModifyResponseBodyGatewayFilterFactory.this.new ResponseAdapter(body, httpHeaders); DefaultClientResponse clientResponse = new DefaultClientResponse(responseAdapter, ExchangeStrategies.withDefaults()); Mono modifiedBody = clientResponse.bodyToMono(inClass).flatMap((originalBody) -> { return ModifyResponseGatewayFilter.this.config.rewriteFunction.apply(exchange, originalBody); }); BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass); CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, exchange.getResponse().getHeaders()); return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> { Flux<DataBuffer> messageBody = outputMessage.getBody(); HttpHeaders headers = this.getDelegate().getHeaders(); if (!headers.containsKey("Transfer-Encoding")) { messageBody = messageBody.doOnNext((data) -> { headers.setContentLength((long)data.readableByteCount()); }); } return this.getDelegate().writeWith(messageBody); })); } public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) { return this.writeWith(Flux.from(body).flatMapSequential((p) -> { return p; })); } }; return chain.filter(exchange.mutate().response(responseDecorator).build()); } public int getOrder() { return -2; } }
2.1.2 GlobalFilter 全域過濾器介面,會作用到所有的Route上,
public interface GlobalFilter {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
三、GatewayFilterFactory
在上一篇 Spring Cloud Gateway 原始碼剖析之Predicate謂詞詳解 中,已經詳細介紹了 PredicateFactory 的各種子類實作,GatewayFilterFactory 也一樣,這里就詳細分析了哈,

歡迎大家關注我的公眾號【老周聊架構】,Java后端主流技術堆疊的原理、原始碼分析、架構以及各種互聯網高并發、高性能、高可用的解決方案,

喜歡的話,一鍵三連走一波,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/273268.html
標籤:其他
