柚子快報邀請碼778899分享:Gateway簡述
柚子快報邀請碼778899分享:Gateway簡述
前言
? 在微服務(wù)架構(gòu)中,一個系統(tǒng)會被拆分為很多個微服務(wù)。那么作為客戶端調(diào)用多個微服務(wù)接口的地址。另外微服務(wù)架構(gòu)的請求中,90%的都攜帶認(rèn)證信息/用戶登錄信息,都需要做相關(guān)的限制管理,API網(wǎng)關(guān)由此應(yīng)允而生。
這樣的架構(gòu)會存在許多的問題:
客戶端多次請求不同的微服務(wù),增加客戶端代碼或配置編寫的復(fù)雜性。認(rèn)證復(fù)雜,每個服務(wù)都需要獨立認(rèn)證。存在跨域請求,在一定場景下處理相對復(fù)雜。
? 所謂的API網(wǎng)關(guān),就是指系統(tǒng)的統(tǒng)一入口,它封裝了應(yīng)用程序的內(nèi)部結(jié)構(gòu),為客戶端提供統(tǒng)一服務(wù),一些與業(yè)務(wù)本身功能無關(guān)的公共邏輯可以在這里實現(xiàn),諸如認(rèn)證、鑒權(quán)、監(jiān)控、路由轉(zhuǎn)發(fā)等等。
網(wǎng)關(guān)的核心功能特性:
請求路由權(quán)限控制限流
常見網(wǎng)關(guān)
1)Ngnix+lua
? 基于Nginx+Lua開發(fā),性能高,穩(wěn)定,有多個可用的插件(限流、鑒權(quán)等等)可以開箱即用。
? 使用nginx的反向代理和負(fù)載均衡可實現(xiàn)對api服務(wù)器的負(fù)載均衡及高可用。 lua是一種腳本語言,可以來編寫一些簡單的邏輯, nginx支持lua腳本。
缺點:
只支持Http協(xié)議。二次開發(fā),自由擴(kuò)展困難。提供管理API,缺乏更易用的管控、配置方式。
2)Zuul
? Zuul的路由功能實現(xiàn)了統(tǒng)一處理外部請求的功能,負(fù)責(zé)將外部請求轉(zhuǎn)發(fā)到具體的微服務(wù)實例上,是實現(xiàn)外部訪問統(tǒng)一入口的基礎(chǔ)。zuul還提供過濾器功能,負(fù)責(zé)對請求的處理過程進(jìn)行干預(yù),是實現(xiàn)請求校驗、服務(wù)聚合等功能的基礎(chǔ)。Zuul的底層基于Servlet,本質(zhì)上就是一系列的filter過濾器,也是它的核心。Zuul2是采用Netty實現(xiàn)異步IO。
缺點:
缺乏管控,無法動態(tài)配置。依賴組件較多。處理Http請求依賴的是Web容器,性能不如Nginx。
3)Gateway
? 底層使用了高性能的通信框架Netty,提供了異步支持,提供了抽象負(fù)載均衡,提供了抽象流控,并默認(rèn)實現(xiàn)了RedisRateLimiter。
介紹
? Spring Cloud Gateway基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān),它旨在為微服務(wù)架構(gòu)提供一種簡單有效的統(tǒng)一的 API 路由管理方式?;?Filter 鏈的方式提供了網(wǎng)關(guān)基本的功能,例如:安全,監(jiān)控/指標(biāo),和限流。底層使用了高性能的通信框架Netty,提供了異步支持,提供了抽象負(fù)載均衡,提供了抽象流控,并默認(rèn)實現(xiàn)了RedisRateLimiter。
? 為了提升網(wǎng)關(guān)的性能,SpringCloud Gateway是基于WebFlux框架實現(xiàn)的,而WebFlux框架底層則使用了高性能的Reactor模式通信框架Netty。
特性
(1)基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
(2)可集成 Hystrix 、Sentinel實現(xiàn)熔斷降級
(3)集成 Spring Cloud DiscoveryClient
(4)Predicates 和 Filters 作用于特定路由,易于編寫的 Predicates 和 Filters
(5)具備一些網(wǎng)關(guān)的高級功能:動態(tài)路由、限流、路徑重寫
三大核心概念:
Filter(過濾器):
? **使用它攔截和修改請求,并且對上游的響應(yīng),進(jìn)行二次處理。**org.springframework.cloud.gateway.filter.GatewayFilter的實例,用于請求被路由前或者之后對請求進(jìn)行修改。
pre類型
? Filter在pre類型的過濾器可以做參數(shù)效驗、權(quán)限效驗、流量監(jiān)控、日志輸出、協(xié)議轉(zhuǎn)換等。
post類型
? Filter在post類型的過濾器可以做響應(yīng)內(nèi)容、響應(yīng)頭的修改、日志輸出、流量監(jiān)控等
Route(路由):
? 網(wǎng)關(guān)配置的基本組成模塊,和Zuul的路由配置模塊類似。一個Route模塊由一個 ID,一個目標(biāo) URI,一組斷言和一組過濾器定義。如果斷言為真,則路由匹配,目標(biāo)URI會被訪問。
Predicate(斷言):
? 這是一個 Java 8 的 Predicate。輸入類型是一個 ServerWebExchange??梢允褂盟鼇砥ヅ鋪碜?HTTP 請求的任何內(nèi)容,例如 headers 或參數(shù)。如果請求與斷言相匹配則進(jìn)行路由。
Gateway核心架構(gòu)
1、路由 Route
? 路由(Route) 是 gateway 中最基本的組件之一,表示一個具體的路由信息載體。主要定義了下面的幾個信息:
id:路由標(biāo)識符,區(qū)別于其他 Route。uri:路由指向的目的地 uri,即客戶端請求最終被轉(zhuǎn)發(fā)到的微服務(wù)。order:用于多個 Route 之間的排序,數(shù)值越小排序越靠前,匹配優(yōu)先級越高。predicate:斷言的作用是進(jìn)行條件判斷,只有斷言都返回真,才會真正的執(zhí)行路由。filter:過濾器用于修改請求和響應(yīng)信息。predicate:斷言,用于進(jìn)行條件判斷,只有斷言都返回真,才會真正的執(zhí)行路由。
2、過濾器
? Gateway的過濾器的作用是:是在請求的傳遞過程中,對請求和響應(yīng)做一些手腳。
1)Gateway的過濾器的生命周期:
? Pre:這種過濾器在請求被路由之前調(diào)用。可利用這種過濾器實現(xiàn)身份驗證、在集群中選擇 請求的微服務(wù)、記錄調(diào)試信息等。
? Post:這種過濾器在路由到微服務(wù)以后執(zhí)行。這種過濾器可用來為響應(yīng)添加標(biāo)準(zhǔn)的HTTP Header、收集統(tǒng)計信息和指標(biāo)、將響應(yīng)從微服務(wù)發(fā)送給客戶端等。
? Gateway 的Filter從作用范圍可分為兩種: GatewayFilter與GlobalFilter。GatewayFilter:應(yīng)用到單個路由或者一個分組的路由上;GlobalFilter:應(yīng)用到所有的路由上。
2)GatewayFilter 局部過濾器
? 局部過濾器是針對單個路由的過濾器。他分為內(nèi)置過濾器和自定義過濾器。在SpringCloud Gateway中內(nèi)置了很多不同類型的網(wǎng)關(guān)路由過濾器。
內(nèi)置的局部過濾器內(nèi)容
過濾器工廠作用參數(shù)AddRequestHeader為原始請求添加HeaderHeader的名稱及值A(chǔ)ddRequestParameter為原始請求添加請求參數(shù)參數(shù)名稱及值A(chǔ)ddResponseHeader為原始響應(yīng)添加HeaderHeader的名稱及值DedupeResponseHeader剔除響應(yīng)頭中重復(fù)的值需要去重的Header名稱及去重策略Hystrix為路由引入Hystrix的斷路器保護(hù)HystrixCommand 的名稱FallbackHeaders為fallbackUri的請求頭中添加具體的異常信息Header的名稱PrefixPath為原始請求路徑添加前綴前綴路徑PreserveHostHeader為請求添加一個preserveHostHeader=true的屬性,路由過濾器會檢查該屬性以決定是否要發(fā)送原始的Host無RequestRateLimiter用于對請求限流,限流算法為令牌桶keyResolver、 rateLimiter、 statusCode、 denyEmptyKey、 emptyKeyStatusRedirectTo將原始請求重定向到指定的URLhttp狀態(tài)碼及重定向的urlRemoveHopByHopHeadersFilter為原始請求刪除IETF組織規(guī)定的一系列Header默認(rèn)就會啟用,可以通過配置指定僅刪除哪些HeaderRemoveRequestHeader為原始請求刪除某個HeaderHeader名稱RemoveResponseHeader為原始響應(yīng)刪除某個HeaderHeader名稱RewritePath重寫原始的請求路徑原始路徑正則表達(dá)式以及重寫后路徑的正則表達(dá)式RewriteResponseHeader重寫原始響應(yīng)中的某個HeaderHeader名稱,值的正則表達(dá)式,重寫后的值SaveSession在轉(zhuǎn)發(fā)請求之前,強(qiáng)制執(zhí)行WebSession::save操作無secureHeaders為原始響應(yīng)添加一系列起安全作用的響應(yīng)頭無,支持修改這些安全響應(yīng)頭的值SetPath修改原始的請求路徑修改后的路徑SetResponseHeader修改原始響應(yīng)中某個Header的值Header名稱,修改后的值SetStatus修改原始響應(yīng)的狀態(tài)碼HTTP 狀態(tài)碼,可以是數(shù)字,也可以是字符串StripPrefix用于截斷原始請求的路徑使用數(shù)字表示要截斷的路徑的數(shù)量Retry針對不同的響應(yīng)進(jìn)行重試retries、statuses、methods、seriesRequestSize設(shè)置允許接收最大請求包的大小。如果請求包大小超過設(shè)置的值,則返回 413 Payload Too Large請求包大小,單位為字節(jié),默認(rèn)值為5MModifyRequestBody在轉(zhuǎn)發(fā)請求之前修改原始請求體內(nèi)容修改后的請求體內(nèi)容ModifyResponseBody修改原始響應(yīng)體的內(nèi)容修改后的響應(yīng)體內(nèi)容
? 當(dāng)內(nèi)置過濾器沒有辦法滿足需求的時候,就可以通過繼承AbstractGatewayFilterFactory來實現(xiàn)自定義過濾器。
3)GlobalFilter 全局過濾器
? 全局過濾器作用于所有路由, 無需配置。通過全局過濾器可以實現(xiàn)對權(quán)限的統(tǒng)一校驗,安全性驗證等功能。SpringCloud Gateway內(nèi)部也是通過一系列的內(nèi)置全局過濾器對整個路由轉(zhuǎn)發(fā)進(jìn)行處理。
?
全局過濾器常用于訪問鑒權(quán),大概執(zhí)行邏輯如下:
當(dāng)客戶端第一次請求服務(wù)時,服務(wù)端對用戶進(jìn)行信息認(rèn)證(登錄)。 認(rèn)證通過,將用戶信息進(jìn)行加密形成token,返回給客戶端,作為登錄憑證。 以后每次請求,客戶端都攜帶認(rèn)證的token。 服務(wù)端對token進(jìn)行解密,判斷是否有效。 //鑒權(quán)示例
@Component
public class AuthGlobalFilter implements GlobalFilter {
@Override
public Mono
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (StringUtils.isBlank(token)) {
System.out.println("鑒權(quán)失敗");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
網(wǎng)關(guān)限流
? 網(wǎng)關(guān)是所有請求的公共入口,所以可以在網(wǎng)關(guān)進(jìn)行限流??梢圆捎肧entinel組件/Hystrix組件來實現(xiàn)網(wǎng)關(guān)的限流。
? 從1.6.0版本開始,Sentinel提供了SpringCloud Gateway的適配模塊,可以提供兩種資源維度的限流:
route維度:即在Spring配置文件中配置的路由條目,資源名為對應(yīng)的routeId自定義API維度:用戶可以利用Sentinel提供的API來自定義一些API分組
? 當(dāng)在限流的時候,不想返回默認(rèn)的錯誤,那么就需要自定義錯誤,指定自定義的返回格式。
//route維度
@PostConstruct
public void initBlockHandlers() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
public Mono
Map map = new HashMap<>();
map.put("code", 0);
map.put("message", "接口被限流了");
return ServerResponse.status(HttpStatus.OK).
contentType(MediaType.APPLICATION_JSON).
body(BodyInserters.fromValue(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
//--------------------------------------------------------------------
//自定義API維度
@PostConstruct
private void initCustomizedApis() {
Set
ApiDefinition api1 = new ApiDefinition("order_api")
.setPredicateItems(new HashSet
add(new ApiPathPredicateItem().setPattern("/order-serv/api/**"). setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(api1);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
@PostConstruct
private void initGatewayRules() {
Set
rules.add(new GatewayFlowRule("product_route")
.setCount(3)
.setIntervalSec(1)
);
rules.add(new GatewayFlowRule("order_api").
setCount(1).
setIntervalSec(1));
GatewayRuleManager.loadRules(rules);
}
執(zhí)行流程
Gateway Client 向 Spring Cloud Gateway 發(fā)送請求請求首先會被 HttpWebHandlerAdapter 進(jìn)行提取組裝成網(wǎng)關(guān)上下文然后網(wǎng)關(guān)的上下文會傳遞到 DispatcherHandler ,它負(fù)責(zé)將請求分發(fā)給 RoutePredicateHandlerMappingRoutePredicateHandlerMapping 負(fù)責(zé)路由查找,并根據(jù)路由斷言判斷路由是否可用如果過斷言成功,由FilteringWebHandler 創(chuàng)建過濾器鏈并調(diào)用通過特定于請求的 Fliter 鏈運行請求,F(xiàn)ilter 被虛線分隔的原因是Filter可以在發(fā)送代理請求之前(pre)和之后(post)運行邏輯執(zhí)行所有pre過濾器邏輯。然后進(jìn)行代理請求。發(fā)出代理請求后,將運行“post”過濾器邏輯。處理完畢之后將 Response 返回到 Gateway 客戶端
其他
1、Nginx網(wǎng)關(guān)和Gateway網(wǎng)關(guān)的區(qū)別
? Nignx是流量網(wǎng)關(guān),Gateway是業(yè)務(wù)網(wǎng)關(guān)。 一般流量網(wǎng)關(guān)配置在前,業(yè)務(wù)網(wǎng)關(guān)配置在后。
? 流量網(wǎng)關(guān)相當(dāng)于訪問的一個總?cè)肟?,前端頁面的一個容器,類似于防火。主要的功能有管理日志,流量監(jiān)控,黑白名單,請求的負(fù)載均衡,全局限流等。Nginx是C語言寫的,Nginx主要是負(fù)載均衡,反向代理,以及做web服務(wù)器。
? 而業(yè)務(wù)網(wǎng)關(guān)是針對具體的后端應(yīng)用和服務(wù),主要的功能是緩存策略、鑒權(quán)策略等。GateWay是java語言寫的,Gateway主要是路由、斷言和過濾器,利用這些可以做流控。
2、Gateway 組件缺陷以及優(yōu)化思路
問題1、每次請求級別都會重新組裝出一個 FilterChain,并進(jìn)行排序,內(nèi)存分配和排序會占用 CPU
問題2、在默認(rèn)情況下,如果其中一個路由配置出錯了,會導(dǎo)致整個網(wǎng)關(guān)路由不可用,除非 isFailOnRouteDefinitionError 被關(guān)閉。
問題3、路由內(nèi)存優(yōu)化,同一份路由的配置內(nèi)容竟然以 3 種形式常駐于內(nèi)存中。
問題4、內(nèi)存泄漏優(yōu)化。通訊底座是netty,通信內(nèi)容較大時,例如文件上傳,則會觸發(fā)內(nèi)存的新分配,而 SpringCloud Gateway 在對接 netty 時存在邏輯缺陷,會導(dǎo)致新分配的池化內(nèi)存無法完全回收,導(dǎo)致堆外內(nèi)存泄漏。并且這塊堆外內(nèi)存時 netty 使用 unsafe 自行分配的,通過常規(guī)的 JVM 工具還無法觀測,非常隱蔽。
問題5、預(yù)構(gòu)建 URI 。針對不可變對象的一次變更,從而進(jìn)行了一次深拷貝,重新重構(gòu)了一個 URI
問題6、對象緩存。盡量避免調(diào)用鏈路中出現(xiàn) new 關(guān)鍵字,它會加大 CPU 的開銷,從而影響 IO,可以使用 ThreadLocal 或者對象池化技術(shù)進(jìn)行對象復(fù)用。
來自SpringCloud Gateway 在微服務(wù)架構(gòu)下的最佳實踐
3、登錄鑒權(quán)圖
總結(jié)
? Gateway主要用于為微服務(wù)架構(gòu)提供一種簡單有效的統(tǒng)一的 API 路由管理方式,主要用于微服務(wù)API共性做統(tǒng)一要求。采用Filter鏈的形式,對API做了請求頭部信息做限制,對微服務(wù)常用的認(rèn)證授權(quán)也做了對應(yīng)限制,并可對高并發(fā)進(jìn)行流量限制。經(jīng)過層層過濾之后,對請求接口進(jìn)行服務(wù)接口路由到對應(yīng)的服務(wù)接口。
柚子快報邀請碼778899分享:Gateway簡述
相關(guān)鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。