spring-cloud-gateway之handler

引言

本篇文字主要講解spring-cloud-gateway的handler部分叽掘,參考官方的gateway處理流程圖可以知道handler是gateway的核心控制部分谨朝,其控制著request在gateway的整個生命周期。我們可以看到抽碌,一個請求由Client發(fā)出旺订,被spring-web-server監(jiān)聽,經(jīng)過gateway-handler-mapping之后請求便進入了gateway部分的代碼實現(xiàn)部分赠摇,也就表明gateway是通過Gateway Web Hnadler來與web框架交接工作的固逗。那么本節(jié)的重點則用于講解handler的工作交接部分以及如何疏通整個工作流的,扮演這個交接工作角色的是FilteringWebHandler藕帜,實現(xiàn)web server的WebHandler接口烫罩。

FilteringWebHandler | loadFilters(List<GlobalFilter> filters)

關(guān)注final List<GatewayFilter> globalFilters的初始化,會將Configuration注入的GlobalFilter bean初始化至globalFilters洽故;這里有兩個目標(biāo)轉(zhuǎn)換類贝攒,在loadFilters方法中map函數(shù)對每一個GlobalFilter做包裝轉(zhuǎn)換,對于實現(xiàn)了Ordered接口最終轉(zhuǎn)換出OrderedGatewayFilter时甚,沒有排序的則轉(zhuǎn)換出GatewayFilterAdapter隘弊;兩個目標(biāo)類均是GatewayFilter接口的實現(xiàn)類哈踱,GatewayFilterAdapter是FilteringWebHandler的私有嵌套類,理想情況不應(yīng)該存在不實現(xiàn)Ordered接口的全局過濾器梨熙;而OrderedGatewayFilter位于filter包下嚣鄙,與GlobalFilter在同一包下聲明,僅僅是對GatewayFilterAdapter的包裝串结,將其GatewayFilterAdapter和order映射到字段哑子。

FilteringWebHandler

這里的loadFilters加載的是全局過濾器,與RouteDefinitionRouteLocator中的loadFilters函數(shù)不同肌割,RouteDefinitionRouteLocator中是加載的配置的gatewayFilter卧蜓,即每次請求都需要根據(jù)Route和過濾器工廠集合來加載一次,而全局過濾器的加載只發(fā)生在進程啟動時的一次性加載行為把敞,但是最終加載結(jié)果類型一樣都是OrderedGatewayFilter類型弥奸。

GatewayFilterAdapter
OrderedGatewayFilter

FilteringWebHandler | handle(ServerWebExchange exchange)

handle方法處理一個來自web server(WebFlux)的http(web server將一個請求的request和response抽象成一個ServerWebExchange)請求,首先在exchange的attributes中獲取當(dāng)前請求配置或者代碼預(yù)先設(shè)置的gatewayFilters奋早,然后與當(dāng)前全局過濾器轉(zhuǎn)換出來的gatewayFilter進行組合盛霎,最后new一個GatewayFilterChain來對exchange過濾。

GatewayFilterChain處理過程

RoutePredicateHandlerMapping

RoutePredicateHandlerMapping兩個重要屬性耽装,一個是FilteringWebHandler愤炸;一個是RouteLocator接口的實現(xiàn),默認(rèn)是CachingRouteLocator掉奄。

webHandler就是代理了FilteringWebHandler的處理能力规个,調(diào)用其handle函數(shù)處理請求的ServerWebExchange。

handler模塊處理request的入口是getHandlerInternal函數(shù)姓建,主要邏輯在lookupRoute(ServerWebExchange exchange)方法中诞仓,為每一個請求分配路由,這里并沒有將路由作為返回結(jié)果速兔,而是將其set進attributes屬性集合中墅拭。

路由匹配邏輯觸發(fā)函數(shù)

從方法邏輯處分析,首先調(diào)用了CachingRouteLocator的getRoutes()獲取當(dāng)前內(nèi)存中所有已存在的Route集合涣狗,然后有序遍歷concatMap()中通過filterWhen來使用每一個Route的predicate(AsyncPredicate)來匹配當(dāng)前的request谍婉,這個predicate是一個函數(shù)接口實現(xiàn),其中and操作符將多個配置斷言進行聚合操作的屑柔,這部分可以參考對Route部分的講解屡萤。

路由斷言工廠

gateway路由斷言

在spring-cloud-gateway的架構(gòu)設(shè)計中,將路由設(shè)計為spring-webflux的一部分掸宛,對于webflux mapping的請求進行匹配死陆;在此基礎(chǔ)上gateway內(nèi)置了許多的路由斷言,均位于handler包的predicate下;主要用于斷言匹配Http請求的不同屬性措译,通過斷言組合來實現(xiàn)多屬性匹配别凤,斷言作用發(fā)生于filter之前,在Exchange進入Filter之前對請求屬性做處理匹配领虹,所以斷言僅僅對于request有效规哪。

從斷言的命名可以明白大部分的斷言作用,其實在使用過程中塌衰,大部分?jǐn)嘌詰?yīng)用并不廣泛诉稍,正常情況下都會配置PathRoutePredicateFactory斷言來斷言區(qū)分path,其他的用于與其組合作用于某個下游服務(wù)或者絕對路由設(shè)置最疆。下面圖片列舉出接口-抽象類-實現(xiàn)類的關(guān)系圖杯巨,與GatewayFilter過濾器工廠類繼承依賴關(guān)系極度相似。

接口-類

對于每一個Route的定義中努酸,均有相應(yīng)的predicate聲明服爷,可以在配置文件或者代碼中進行配置。

AfterRoutePredicateFactory

AfterRoutePredicateFactory斷言用于斷言請求發(fā)生時間获诈,配置參數(shù)只有一個datetime的String類型參數(shù)仍源,在GatewayAutoConfiguration中注入,匹配配置時間之后的所有請求舔涎,在一些預(yù)熱活動等場景可以配合其他斷言來使用笼踩。

BeforeRoutePredicateFactory

BeforeRoutePredicateFactory與AfterRoutePredicateFactory對應(yīng),匹配配置時間之前的所有請求终抽,能夠與其他比如Path斷言組合使用戳表。

配置示例

BetweenRoutePredicateFactory

BetweenRoutePredicateFactory是BeforeRoutePredicateFactory和AfterRoutePredicateFactory的組合體桶至。

Between配置示例

CloudFoundryRouteServiceRoutePredicateFactory

CloudFoundryRouteServiceRoutePredicateFactory官方并沒有作使用說明昼伴,從代碼提交上看來是配合HeaderRoutePredicateFactory使用,用于對request進行forward的镣屹,目前看來應(yīng)用場景并不明確圃郊。

CookieRoutePredicateFactory

CookieRoutePredicateFactory斷言,用于匹配指定Cookie的請求女蜈,結(jié)合官方說明可知其意圖在過濾指定的請求持舆;比如配置過濾不同設(shè)備端的web請求等場景。

image.png
image.png

HeaderRoutePredicateFactory

HeaderRoutePredicateFactory是Http Header層的斷言伪窖,匹配指定header參數(shù)逸寓,同時也可以指定參數(shù)所匹配的表達式,沒有進行實際應(yīng)用過覆山。

HostRoutePredicateFactory

HostRoutePredicateFactory配置指定Host模式的請求(比如二級域名的正則匹配)竹伸,并將匹配結(jié)果以鍵值對形式放入attributes屬性集合中。

MethodRoutePredicateFactory

MethodRoutePredicateFactory很好理解,即匹配指定Method的請求勋篓,否則被忽略吧享,如果一個路由只允許某些Http方法的請求,可以使用此配置譬嚣,來限制不合法的請求钢颂。

PathRoutePredicateFactory

PathRoutePredicateFactory是斷言中應(yīng)用最廣泛的,也是路由匹配的核心組件拜银,根據(jù)請求的Uri進行模式匹配區(qū)分路由的殊鞭。

QueryRoutePredicateFactory

QueryRoutePredicateFactory作用于請求的query參數(shù),可以用于限制某些請求必要的query參數(shù)尼桶。

ReadBodyPredicateFactory

ReadBodyPredicateFactory個人覺得不是一個實用的斷言钱豁,可以參考Filter中ModifyBody部分的實現(xiàn),涉及異步流的修改疯汁。

RemoteAddrRoutePredicateFactory

RemoteAddrRoutePredicateFactory斷言可以過濾掉非指定ip地址段的請求牲尺;個人覺得可以寫一個ExcludeRemoteAddrRoutePredicateFactory斷言,用于拒絕指定ip的請求幌蚊,或者從黑名單中匹配拒絕谤碳,粗略的防止hack攻擊。

WeightRoutePredicateFactory

WeightRoutePredicateFactory權(quán)重路由溢豆,可以用于恢復(fù)發(fā)布或者AB test場景蜒简,互聯(lián)網(wǎng)應(yīng)用中常見的需求,這個斷言需要集成WeightCalculatorWebFilter過濾器來起作用漩仙。

具體配置可以參考:Canary-test using Spring Cloud Gateway

Sumarry

spring-cloud-gateway中predicate是過濾匹配請求的第一步搓茬,主要作用是為每個請求精準(zhǔn)匹配出其路由,其中關(guān)鍵精彩實現(xiàn)部分在于作者合理利用函數(shù)式接口實現(xiàn)類AsyncPredicate類將多個predicate進行了聚合操作队他,這是值得Java編程學(xué)習(xí)的卷仑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市麸折,隨后出現(xiàn)的幾起案子锡凝,更是在濱河造成了極大的恐慌,老刑警劉巖垢啼,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窜锯,死亡現(xiàn)場離奇詭異,居然都是意外死亡芭析,警方通過查閱死者的電腦和手機锚扎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馁启,“玉大人驾孔,你說我怎么就攤上這事。” “怎么了助币?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵浪听,是天一觀的道長。 經(jīng)常有香客問我眉菱,道長迹栓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任俭缓,我火速辦了婚禮克伊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘华坦。我一直安慰自己愿吹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布惜姐。 她就那樣靜靜地躺著犁跪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪歹袁。 梳的紋絲不亂的頭發(fā)上坷衍,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音条舔,去河邊找鬼枫耳。 笑死,一個胖子當(dāng)著我的面吹牛孟抗,可吹牛的內(nèi)容都是我干的迁杨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼凄硼,長吁一口氣:“原來是場噩夢啊……” “哼铅协!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起帆喇,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤警医,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后坯钦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡侈玄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年婉刀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片序仙。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡突颊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情律秃,我是刑警寧澤爬橡,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站棒动,受9級特大地震影響糙申,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜船惨,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一柜裸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粱锐,春花似錦疙挺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至恶座,卻和暖如春锦爵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奥裸。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工险掀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人湾宙。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓樟氢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侠鳄。 傳聞我的和親對象是個殘疾皇子埠啃,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容