Spring Cloud Gateway源碼導(dǎo)讀:
首先我們觀察在引入了Spring Cloud Gateway
后自動裝配都做了什么?從Spring Cloud Gateway
包下找到spring.factories
赘风,查看EnableAutoConfiguration
項即,仔細(xì)觀察后不難發(fā)現(xiàn)關(guān)鍵配置項即為GatewayAutoConfiguration
與GatewayReactiveLoadBalancerClientAutoConfiguration
(需要配合spring-cloud-loadbalancer
一起使用)括改。
那么我們分別來看看這兩個配置類都做了什么错邦。
GatewayAutoConfiguration
該配置類中主要裝配了如下幾種類型的對象:
- RouteDefinitionLocator(Properties)
- RouteDefinitionRepository(Redis探赫、InMemory)
- RouteLocator(RouteDefinition)
- RouteRefreshListener
- HandlerMapping(RoutePredicateHandlerMapping)
- WebHandler(FilteringWebHandler)
- GlobalFilters
- Predicate Factory Beans
- GatewayFilter Factory Beans
下面我們依次介紹上述各對象的作用
RouteDefinitionLocator
可以將名稱拆開看,即RouteDefinition
和Locator
撬呢,其中RouteDefinition
與Spring Beans
中的BeanDefinition
類似期吓,從名字上也能看出其實就是用來定義Route
的,用來記錄Route
的關(guān)鍵屬性倾芝,例如Predicates
讨勤、Filters
、url
等晨另。
而Locator
則是用來從特定的位置讀取RouteDefinition
潭千,目前Spring Cloud Gateway
默認(rèn)是從Properties
來讀取RouteDefinition
。讀取后交給RouteLocator
實例化為Route
對象借尿。
RouteDefinitionRepository
Spring Cloud Gateway
提供InMemory
刨晴、Redis
等的RouteDefinitionRepository
,主要用來動態(tài)添加RouteDefinition
路翻,需要注意的是InMemory
通常在Spring Actuator
中打開routes
端點即可使用狈癞,在添加成功后需要發(fā)出RouteRefresh
事件即可更新內(nèi)存中的路由。
RouteLocator
默認(rèn)為RouteDefinitionRouteLocator
茂契,主要作用是根據(jù)RouteDefinitionLocator
中返回的RouteDefinition
創(chuàng)建Route
對象蝶桶,核心操作是將RouteDefinition
中定義的Predicate Factory
、Filter Factory
實例化掉冶,最終封裝在Route
對象中真竖,以供請求進(jìn)來時篩選路由脐雪。
RouteRefreshListener
路由發(fā)生更新時需要發(fā)布RouteRefresh
事件,該監(jiān)聽器負(fù)責(zé)更新內(nèi)存中的路由列表恢共。
HandlerMapping
當(dāng)DispatcherHandler
分發(fā)請求時調(diào)用HandlerMapping.getHandler
方法來獲取HandlerAdapter
以供后續(xù)鏈?zhǔn)秸{(diào)用战秋,Spring Cloud Gateway
默認(rèn)是由RoutePredicateHandlerMapping
處理。在該處理器繼承自AbstractHandlerMapping
讨韭,并實現(xiàn)抽象方法getHandlerInternal
脂信。當(dāng)有請求進(jìn)來時,通過lookupRoute
尋找內(nèi)存中所有的Route
透硝,并通過路由的Predicate
尋找與當(dāng)前請求相匹配的路由狰闪,將其放進(jìn)exchange后,最終返回FilteringWebHandler
蹬铺。
WebHandler
當(dāng)DispatcherHandler
從HandlerMapping
中獲取到了HandlerAdapter
后,隨即立即調(diào)用HandlerAdapter
來處理請求秉撇,上述RoutePredicateHandlerMapping
返回的FilteringWebHandler
是一種WebHandler
甜攀,由SimpleHandlerAdapter
負(fù)責(zé)處理,在FilteringWebHandler
中會將Global Filters
與Route
中定義的Gateway Filters
合并琐馆,按照Order
排序后封裝成DefaultGatewayFilterChain
依次后調(diào)用filter
方法规阀。
GlobalFilters
在純Spring Cloud Gateway
環(huán)境下存在9個全局過濾器,他們按照執(zhí)行順序分別是:
名稱 | Order | 作用 |
---|---|---|
RemoveCachedBodyFilter | Integer.MIN_VALUE | |
AdaptCachedBodyGlobalFilter | Integer.MIN_VALUE + 1000 | |
NettyWriteResponseFilter | -1 | 用來寫響應(yīng)給客戶端 |
ForwardPathFilter | 0 | 若Route中定義的uri是forward類型瘦麸,則將exchange中的request修改為forward類型谁撼。 |
RouteToRequestUrlFilter | 10000 | 取出Route中定義的uri,將其設(shè)置在exchange中 |
NoLoadBalancerClientFilter | 10150 | 在GatewayNoLoadBalancerClientAutoConfiguration中定義滋饲,不使用loadBalance厉碟。 |
WebsocketRoutingFilter | Integer.MAX_VALUE - 1 | 從exchange中取出RouteToRequestUrlFilter中設(shè)置的uri,處理websocket協(xié)議下的路由 |
NettyRoutingFilter | Integer.MAX_VALUE | 從exchange中取出RouteToRequestUrlFilter中設(shè)置的uri屠缭,處理http箍鼓、https協(xié)議下的路由,主要作用是創(chuàng)建新的httpclient呵曹,根據(jù)uri發(fā)送請求并增加request及response處理款咖,同時超時處理也在這個位置。 |
ForwardRoutingFilter | Integer.MAX_VALUE | 如果是forward類型請求奄喂,則交給dispatcherhandler重新處理铐殃。 |
Predicate Factory Beans
內(nèi)置的Predicate
工廠處理類,用來根據(jù)RouteDefinition中的配置生成對應(yīng)的Predicate
跨新。在HandlerMapping
中通過調(diào)用Predicate.test
方法匹配請求與路由富腊。
PS.這里有個性能瓶頸,默認(rèn)策略是循環(huán)遍歷每一個路由的Predicate.test
方法進(jìn)行匹配域帐,當(dāng)路由數(shù)量越來越多時性能急劇下降蟹肘,可根據(jù)實際業(yè)務(wù)中路由的Predicate
類型進(jìn)行優(yōu)化词疼。例如全都是PathRoutePredicate
時,可根據(jù)固有邏輯建立路由標(biāo)識與路由的緩存帘腹,在請求進(jìn)來時快速查找贰盗,找不到時由默認(rèn)邏輯兜底。
GatewayFilter Factory Beans
內(nèi)置的路由級別GatewayFilter
工廠處理類阳欲,用來根據(jù)RouteDefinition中的配置生成對應(yīng)的GatewayFilter
舵盈。在
FilteringWebHandler
中會與GlobalFilter
合并后對請求進(jìn)行處理。
GatewayReactiveLoadBalancerClientAutoConfiguration
當(dāng)引入了spring-cloud-loadbalancer
后球化,該配置類會自動注入ReactiveLoadBalancerClientFilter
從而替代默認(rèn)的NoLoadBalancerClientFilter
秽晚。當(dāng)前版本的Spring Cloud Gateway
原生支持Random
、RoundRobin
兩種負(fù)載策略筒愚,默認(rèn)使用RoundRobin
策略赴蝇。
注意,ReactiveLoadBalancerClientFilter
的Order
與NoLoadBalancerClientFilter
相同巢掺,都為10150句伶。
ReactiveLoadBalancerClientFilter的處理流程
ReactiveLoadBalancerClientFilter
在處理時僅處理lb://
類型的uri
,其原理為從uri
中解析出的host
后陆淀,通過利用NamedContextFactory
創(chuàng)建一個新的以Route id
為name
的ApplicationContext
考余,由LoadBalancerClientConfiguration
自動注入RoundRobinLoadBalancer
到新建的ApplicationContext
中,隨后通過LoadBalancer
從ServiceInstanceListSupplier
中查找出指定host
的所有實例轧苫,根據(jù)負(fù)載均衡算法選取一個示例后返回給ReactiveLoadBalancerClientFilter
楚堤,接著將實例的uri
與原有請求的uri
合并后替換exchange
中的GATEWAY_REQUEST_URL_ATTR
以供后續(xù)NettyRoutingFilter
使用。
大體上的Spring Cloud Gateway
的初始化及處理流程就是這樣含懊,至于每個Filter
的細(xì)節(jié)可以根據(jù)項目中使用到的情況來繼續(xù)研讀身冬。