spring-cloud-gateway之架構設計

spring-cloud-gateway作為cloud體系的一員,其設計思想非常巧妙,項目leader是spring開源主要作者之一的Spencer Gibb。

一、我們首先從gateway的dependencies查看其所依賴 項,gateway本身對spring-boot-starter有依賴,gateway在微服務架構體系當中也是以Java 進程的方式而存在,這樣我們在做二次元開發時可以不需要再次依賴此項;gateway-core的源碼採用流表達式編碼,這裡要求我們的jdk保持在1.8版本以上以及對reactor異步模型有初步認知;其次對eureka的引入,默認採用eureka為服務註冊中心;還有其他的引入比如redis、hystrix等均為功能功能性必要依賴。

spring-cloud-gateway之架構設計

spring-cloud-gateway-core 依賴項截圖


二、工程結構解讀

如圖工程代碼結構非常的清晰和明確,這得益於作者的優秀設計思想,採用工廠模式、門面模式等優秀的代碼設計。

spring-cloud-gateway之架構設計

spring-cloud-gateway 工程結構

1. actuate

actuate 包下GatewayControllerEndpoint.java是一個內嵌endpoint監控api管理類,方便通過api來觀察當前的routes配置和filter配置信息;其中有個POST(/routes/{id})可以運行時添加route配置。spring-boot和spring-cloud內嵌的管理類api的設計初衷便是為了方便與管理類平臺集成,比如spring-cloud-admin。

spring-cloud-gateway之架構設計

2. config

config包下是gateway工程配置類或者項目啟動初始化類, 分類和命名都非常的清晰,通過類名便可知道其中的內部作用,其包內類圖如圖所示:

spring-cloud-gateway之架構設計

<code>GatewayAutoConfiguration.java/<code>

spring-cloud-gateway之架構設計

GatewayAutoConfiguration類從頭部註解可以瞭解其中的類加載順序和依賴條件。

  • Configuration註解是spring ioc的標準配置注入註解;
  • spring.cloud.gateway.enabled配置默認是開啟的,即只要引入了spring-cloud-gateway-starter便開啟了網關;
  • AutoConfigureBefore和AutoConfigureAfter是配置注入的前後順序保證;
  • ConditionalOnClass標註必須依賴的bean條件,RouteLocator、ForwardPathFilter等實例bean都是為WebFilter(DispatcherHandler) 服務的,而GatewayAutoConfiguration類則是負責RouteLocatorBuilder、RetryGatewayFilterFactory等全局單一實例注入的。這個與我們自己spring-boot項目中需要一個注入配置類的作用類似。

<code>GatewayClassPathWarningAutoConfiguration.java/<code>
  • GatewayClassPathWarningAutoConfiguration作用比較單一,是gateway工程啟動過程中的一個加載檢查機制,當綁定條件丟失時會有log警告輸出。

spring-cloud-gateway之架構設計

<code>GatewayEnvironmentPostProcessor.java/<code>
  • 2.2.0-SNAPSHOT版本新增的一個配置類,用於操作進程內部全局環境變量的值,作用與spring-cloud-admin可以動態修改spring-boot的日誌級別類是。
<code>GatewayLoadBalancerClientAutoConfiguration.java/<code>
  • 負責LoadBalancerClientFilter(負載均衡過濾器,在下游服務分佈式多實例情況下做請求負載路由)的初始化注入。
<code>GatewayMetricsAutoConfiguration.java/<code>
  • 負責GatewayMetricsFilter(請求監控全局過濾器)初始化注入。
<code>GatewayNoLoaBalancerClientAutoConfiguration.java/<code>
  • 2.2.0-SNAPSHOT新增配置類,其中聲明瞭一個受保護的內部全局過濾器,在處理請求是沒有負載均衡計算,當RibbonAutoConfiguration類缺失情況下才會啟動,之前gateway工程必須依賴netflix.ribbon作為默認的負載均衡引入,在2.2.0正式版本發佈之後將會取代這個限制,即默認可以不開啟負載均衡。
<code>GatewayProperties.java/<code>
  • spring.cloud.gateway這個配置項下的配置信息定義。主要包括routes、defaultFilters。

<code>GatewayRedisAutoConfiguration.java/<code>
  • gateway的請求限流是通過redis + lua script 來實現的,此類作用不言而喻。
<code>    GlobalCorsProperties.java/<code>
  • Http Cors層面的配置,通常採用默認即可,即http請求不做限制,可以google瞭解一下Cors。
<code>LoadBalancerProperties.java/<code>
  • 結合負載均衡等過濾器使用,其中只有一個配置屬性(private boolean use404)。
<code>HttpClientProperties.java/<code>
  • Gateway依賴webflux,其HttpClient默認丟棄了apache的HttpClient,而是採用的reactor-netty框架封裝的HttpClient,採用的是異步編程模式,HttpClientProperties則是為HttpClient而配置的。
<code>PropertiesRouteDefinitionLocator.java/<code>
  • GatewayProperties的代理類。

3. discovery

discovery包其實跟config包作用很類似,主要是服務發現方面的配置以及服務發現邏輯實現。

spring-cloud-gateway之架構設計

<code>DiscoveryLocatorProperties.java/<code>
  • 配置實現類,srping.cloud.gateway.discovery.locator.enabled默認為false, 必須在配置文件將其配置為true,才能開啟服務發現的功能;srping.cloud.gateway.discovery.locator.routeIdPrefix顯式為下有路由服務添加一個前綴標識;其他配置項採用默認配置即可。

<code>GatewayDiscoveryClientAutoConfiguration.java/<code>
  • 從代碼來看,主要是兩個注入方法discoveryClientRouteDefinitionLocator()和discoveryLocatorProperties();
  • discoveryLocatorProperties()方法向IOC注入一個DiscoveryLocatorProperties類的實例,注意此方法初始化了默認的predicate和FilterDefinition,為具體的服務發現邏輯計算與轉換(discoveryClient.getServices())備用。
spring-cloud-gateway之架構設計

<code>DiscoveryClientRouteDefinitionLocator.java/<code>
  • DiscoveryClientRouteDefinitionLocator這個類可以認為是服務發現的一個代理類,其final類型的屬性主要有DiscoveryClient、DiscoveryLocatorProperties,叢載實現getRouteDefinitions方法。

spring-cloud-gateway之架構設計

  • discoveryClient.getServices()從註冊中心獲取所有的服務;

spring-cloud-gateway之架構設計

  • 默認注入的DiscoveryClient是一個代理client,其中注入了兩個具體的實現類對象,分別是SimpleDicoveryClient和EurekaDiscoveryClient(這是netflix.eureka提供的實現,如果採用zk或者自己實現的註冊中心作為服務發現服務需要自己實現DiscoveryClient這個接口來注入),SimpleDiscoveryClient是gateway自身進程實例的代理,eureka中的才能獲取到註冊中心的服務實例。
  • discoveryClient.getServices()方法的第84行獲取了所有的serviceInstance,然後在89行開始遍歷所有的serviceInstance實例,將每個serviceInstance信息轉換成對應的RouteDedinition對象,依次設置serviceId和利用正則表達式將serviceInstance的服務id轉換成對應的路由uri,並轉換出各個服務特有的predicate和filterDefinition(注意此方法返回結果有內存緩存,會定期做過期清理,默認服務發現間隔1分鐘,不會每次服務調用都會調用此方法)。

4. event

此包定義進程的事件封裝,所有類都繼承至ApplicationEvent抽象類,這是spring框架的內部標準,這個標準也是繼承了jdk的EventObject,至於集成spring開發的應用如果需要採用事件發佈訂閱或者觀察者模式等最好也實現該抽象類;抽象類沒有抽象方法的約束,只有一個時間戳的mark字段,對具體實現沒有任何影響。

spring-cloud-gateway之架構設計

5. filter

filter包是gateway的核心實現(代碼解讀放在後續文章)。

filter包一級目錄是全局過濾器的實現,均實現了GlobalFilter接口和Ordered接口;

factory包下是基於工廠模式實現的工廠過濾器,為可配置的過濾器,可針對服務粒度進行可選配置,或者在代碼中能夠實現api級別的過濾;

headers包針對Http header層面的過濾器,這正常情況運用不到;

retelimit包下是基於redis+lua>

spring-cloud-gateway之架構設計

6. handler

此包下主要是Predicate類工廠聲明,在配置路由設置斷言的時候常用來斷言path、header、method等(源碼解讀放在後續文章)。

spring-cloud-gateway之架構設計

7. route

路由層的抽象與定義,這個與下游服務配置深度綁定,可以想象將一個服務實例抽象為一個RouteDefinition,然後為此route增加其predicate和filter等抽象配置。

spring-cloud-gateway之架構設計

spring-cloud-gateway之架構設計

8. support

工具包,裡面有各種filter邏輯和配置初始化所用的工具類,等同於我們平常的util包。

spring-cloud-gateway之架構設計

三、結語

  本篇文章旨在剖析spring-cloud-gateway-core工程下的結構,總結下來其實我覺得最大的收穫是開源作者對於代碼的合理設計使得包結構非常的簡潔清晰,值得廣大Java愛好者學習,能夠深化行為和命名註釋至自己的code當中;其次對於actuate、config、discovery、event簡單包下的源碼做了解讀,後續章節將會重點專注與filter、handler和route下源碼的解讀,也是gateway框架架構設計精華部分。


附:基於spring-cloud-gateway增強實現參考enhance-gateway。


分享到:


相關文章: