天天看點

Spring Cloud Alibaba - Gateway

Gateway

Spring Cloud Alibaba - Gateway
Spring Cloud Alibaba - Gateway

底層使用Netty架構,性能大于Zuul

Spring Cloud Alibaba - Gateway

配置gateway子產品,一般使用yaml格式:

啟動類中添加注解:

啟動測試,在這裡可能會遇到版本沖突的問題:可以使用ctrl+alt+shift+u ,然後出現如下圖所示,紅色就是就是證明存在jar包沖突

Spring Cloud Alibaba - Gateway

路由:網關的基本建構組成,它由ID,目标URI,謂詞集合和過濾器集合定義,如果集合謂詞為true,則比對路由,否則不比對;

謂詞:這是Java 8函數謂詞,輸入類型是Spring Framework ServerWebExchange,可以比對HTTP請求中的所有内容,例如請求頭或參數;

過濾器:這些是使用特定工廠構造的Spring Framework GatewayFilter執行個體,可以在發送給下遊請求之前或之後修改請求和響應;

下圖從總體上概述了Spring Cloud Gateway的工作方式:

Spring Cloud Alibaba - Gateway

用戶端向Spring Cloud Gateway送出請求,如果網關處理程式映射确定請求與路由比對,則将其發送到網關Web處理程式,該處理程式通過特定于請求的過濾器鍊運作請求,篩選器由虛線分隔的原因是,篩選器可以在發送代理請求之前和之後運作邏輯,所有“前置”過濾器邏輯均被執行,然後發出代理請求,發出代理請求後,将運作“後”過濾器邏輯;在沒有端口的路由中定義URI,HTTP和HTTPS URI的預設端口值分别是80和443

Spring Cloud Gateway将路由比對作為Spring WebFlux HandlerMapping基礎架構的一部分,Spring Cloud Gateway包括許多内置的路由謂詞工廠,所有這些謂詞都與HTTP請求的不同屬性比對,可以将多個路由謂詞工廠結合使用;

總共有11個路由謂詞工廠:

\1. The After Route Predicate Factory

\2. The Before Route Predicate Factory

\3. The Between Route Predicate Factory

\4. The Cookie Route Predicate Factory

\5. The Header Route Predicate Factory

\6. The Host Route Predicate Factory

\7. The Method Route Predicate Factory

\8. The Path Route Predicate Factory

\9. The Query Route Predicate Factory

\10. The RemoteAddr Route Predicate Factory

\11. The Weight Route Predicate Factory

After route謂詞工廠采用一個參數,即datetime(這是一個Java ZonedDateTime),該謂詞比對在指定日期時間之後發生的請求,以下示例配置了路由後謂詞:

Spring Cloud Alibaba - Gateway

這條路由符合2017年1月20日17:42:47時間([America/Denver])之後的任何請求;

時間通過擷取:System.out.println(ZonedDateTime.now());

Before路由謂詞工廠采用一個參數,即datetime(這是一個Java ZonedDateTime),該謂詞比對在指定日期時間之前發生的請求,下面的示例配置路由之前謂詞:

Spring Cloud Alibaba - Gateway

這條路由符合2017年1月20日17:42:47時間([America/Denver])之前的任何請求;

路由謂詞之間的工廠使用兩個參數datetime1和datetime2,它們是java ZonedDateTime對象,該謂詞比對在datetime1之後和datetime2之前發生的請求,datetime2參數必須在datetime1之後,以下示例配置了路由之間的謂詞:

Spring Cloud Alibaba - Gateway

該路線與2017年1月20日山區時間(丹佛)之後和2017年1月21日17:42山區時間(丹佛)之前的任何請求相比對,這對于維護時段可能很有用;

Cookie路由謂詞工廠采用兩個參數,即cookie名稱和一個regexp(這是Java正規表達式),該謂詞比對具有給定名稱且其值與正規表達式比對的cookie,以下示例配置Cookie路由謂詞工廠:

Spring Cloud Alibaba - Gateway

此路由比對具有名為Chocolate的cookie的請求,該cookie的值與ch.p正規表達式比對;

舉例:curl http://192.168.0.104/index --cookie token=123456

header 路由謂詞工廠使用兩個參數,header 名稱和一個regexp(這是Java正規表達式),該謂詞與具有給定名稱的header 比對,該header 的值與正規表達式比對,以下示例配置标頭路由謂詞:

Spring Cloud Alibaba - Gateway

如果請求具有名為X-Request-Id的标頭,且其值與\ d +正規表達式比對(即,其值為一個或多個數字),則此路由比對;

舉例:curl http://192.168.0.104/index --header "X-Request-Id:19228"

host路由謂詞工廠使用一個參數:主機名模式清單,以下示例配置主機路由謂詞:

Spring Cloud Alibaba - Gateway

還支援URI模闆變量(例如{sub} .myhost.org),如果請求的主機标頭的值為www.somehost.org或beta.somehost.org或www.anotherhost.org,則此路由比對;

方法路由謂詞工廠使用方法參數,該參數是一個或多個參數:要比對的HTTP方法,以下示例配置方法route謂詞:

Spring Cloud Alibaba - Gateway

如果請求方法是GET或POST,則此路由比對;

路徑路由謂詞工廠使用兩個參數:Spring PathMatcher模式清單和一個稱為matchOptionalTrailingSeparator的可選标志,以下示例配置路徑路由謂詞:

Spring Cloud Alibaba - Gateway

如果請求路徑為例如/red/1或/red/blue或/blue/green,則此路由比對;

查詢路由謂詞工廠采用兩個參數:必需的參數和可選的regexp(這是Java正規表達式),以下示例配置查詢路由謂詞:

Spring Cloud Alibaba - Gateway

如果請求包含green查詢參數,則前面的路由比對;

Spring Cloud Alibaba - Gateway

如果請求包含值與gree比對的red查詢參數,則上述路由比對;

RemoteAddr路由謂詞工廠使用源清單(最小大小為1),這些源是标記(IPv4或IPv6)字元串,例如192.168.0.1/16(其中192.168.0.1是IP位址,而16是子網路遮罩)),下面的示例配置RemoteAddr路由謂詞:

Spring Cloud Alibaba - Gateway

如果請求的遠端位址是例如192.168.1.10,則此路由比對;

權重路由謂詞工廠采用兩個參數:group和weight(一個int),權重是按組計算的,以下示例配置權重路由謂詞:

Spring Cloud Alibaba - Gateway

這條路由會将約80%的流量轉發至weight_high.org,并将約20%的流量轉發至weight_low.org;

路由過濾器允許以某種方式修改傳入的HTTP請求或傳出的HTTP響應,Spring Cloud Gateway包括許多内置的GatewayFilter工廠;

Spring Cloud Alibaba - Gateway

總共有31個GatewayFilter工廠:

\1. The AddRequestHeader GatewayFilter Factory

\2. The AddRequestParameter GatewayFilter Factory

\3. The AddResponseHeader GatewayFilter Factory

\4. The DedupeResponseHeader GatewayFilter Factory

\5. The Hystrix GatewayFilter Factory

\6. Spring Cloud CircuitBreaker GatewayFilter Factory

\7. The FallbackHeaders GatewayFilter Factory

\8. The MapRequestHeader GatewayFilter Factory

\9. The PrefixPath GatewayFilter Factory

\10. The PreserveHostHeader GatewayFilter Factory

\11. The RequestRateLimiter GatewayFilter Factory

\12. The RedirectTo GatewayFilter Factory

\13. The RemoveRequestHeader GatewayFilter Factory

\14. RemoveResponseHeader GatewayFilter Factory

\15. The RemoveRequestParameter GatewayFilter Factory

\16. The RewritePath GatewayFilter Factory

\17. RewriteLocationResponseHeader GatewayFilter Factory

\18. The RewriteResponseHeader GatewayFilter Factory

\19. The SaveSession GatewayFilter Factory

\20. The SecureHeaders GatewayFilter Factory

\21. The SetPath GatewayFilter Factory

\22. The SetRequestHeader GatewayFilter Factory

\23. The SetResponseHeader GatewayFilter Factory

\24. The SetStatus GatewayFilter Factory

\25. The StripPrefix GatewayFilter Factory

\26. The Retry GatewayFilter Factory

\27. The RequestSize GatewayFilter Factory

\28. The SetRequestHost GatewayFilter Factory

\29. Modify a Request Body GatewayFilter Factory

\30. Modify a Response Body GatewayFilter Factory

\31. Default Filters

Spring Cloud Gateway内置了一系列的路由謂詞工廠,但是如果這些内置的路由謂詞工廠不能滿足業務需求的話,可以自定義路由謂詞工廠來實作特定的需求;

下面列舉兩個例子:

1、要求請求必須攜帶一個token,并且token值等于指定的值,才能通路;

2、要求某個服務的使用者隻允許在23:00 - 6:00這個時間段内才可以通路;

自定義謂詞具體步驟:

(1)首先定義一個配置類,用于承載配置參數;

(2)定義一個路由謂詞工廠;

注:TokenRoutePredicateFactory類,前面的Token與.yml配置檔案裡面配置的名字對應,後面的RoutePredicateFactory名字是固定的,不能随便寫,這是Spring Cloud Gateway的約定,類名須為“謂詞工廠名(比如:Token)” + RoutePredicateFactory

(3)在配置檔案中啟用該路由謂詞工廠,即配置一個Token=123456;

時間格式不是随便配置,而是Spring Cloud Gateway的預設時間格式,采用JDK8裡面的格式化:

<code>DateTimeFormatter dateTimeFormatter = DateTimeFormatter.*ofLocalizedTime*(FormatStyle.*SHORT*); String nowTime = dateTimeFormatter.format(ZonedDateTime.*now*()); System.*out*.println(nowTime);</code>

到此為止就實作了一個自定義路由謂詞工廠,若此時token值不相等,不在允許的通路時間段内,通路就會報404;

以Token為例:

配置類:

自定義路由謂詞工廠:

如果謂詞不比對時,處理傳回404頁面顯然不合規範。需要我們對404進行處理

處理的頂層接口是WebExceptionHandler

預設實作是DefaultErrorWebExceptionHandler

Spring Cloud Alibaba - Gateway

我們需要覆寫它的預設實作DefaultErrorWebExceptionHandler,覆寫裡面的方法getRoutingFunction,getHttpStatus,在方法裡面編寫我們想要傳回的結果

實作類:

除此之外,還需要寫一個配置類,添加相關配置,使得404時,将相關資訊給到上面編寫的處理異常類中,并将該異常類傳回。

網關過濾器的頂層接口是GatewayFilterFactory。通常情況下可以繼承AbstractGatewayFilterFactory實作自定義網關過濾器;或者繼承AbstractNameValueGatewayFilterFactory,該方式配置方式更簡單,然後覆寫裡面的一個方法apply

上面的過濾器工廠是執行在指定路由之上,可以稱為路由過濾器(或者局部過濾器),而全局過濾器是作用于所有的路由上,對所有的路由進行過濾;

全局過濾器的頂層接口是GlobalFilter ,和GatewayFilter 有一樣的接口定義,隻不過GlobalFilter 會作用于所有路由;

全局過濾器有執行順序問題,通過getOrder()方法的傳回值決定執行順序,數值越小越靠前執行;

Spring cloud gateway預設内置了很多全局過濾器,比如:

\1. Combined Global Filter and GatewayFilter Ordering

\2. Forward Routing Filter

\3. The LoadBalancerClient Filter

\4. The ReactiveLoadBalancerClientFilter

\5. The Netty Routing Filter

\6. The Netty Write Response Filter

\7. The RouteToRequestUrl Filter

\8. The Websocket Routing Filter

\9. The Gateway Metrics Filter

\10. Marking An Exchange As Routed

當然我們也可以自定義全局過濾器

一經實作,就生效。隻要滿足實作要求,就實作全局過濾。

實作原理是在全局LoadBalancerClientFilter中進行攔截,然後再該過濾器中依賴LoadBalancerClient loadBalancer,而此負載均衡接口的具體實作是RibbonLoadBalancerClient,即spring cloud gateway已經整合好了ribbon,已經可以實作負載均衡,我們不需要做任何工作,網關對後端微服務的轉發就已經具有負載均衡功能;

網關內建Sentinel是為了流控熔斷降級,具體內建整合步驟如下:

1、添加依賴;

*

2、在gateway配置檔案中添加sentinel控制台配置;

3、寫代碼,在spring容器中配置一個Sentinel的全局過濾器;

4、可以進行測試;

在Gateway的配置類(GatewayConfiguration)中,注入一個執行個體限流時傳回BlockRequestHandler

(1)配置依賴;

(2)暫時不需要配置;

(3)寫代碼;

(4)配置SPI;

resources\META-INF\services\com.alibaba.csp.sentinel.init.InitFunc

放入第三步類的路徑(copy reference)

1、添加sentinel-datasource-nacos依賴;

2、application.properties配置持久化資料源;

3、在nacos配置中心配置流控規則(每個route都可以配置逗号隔開):

Spring Cloud Alibaba - Gateway

(1)根據自動裝配spring-cloud-gateway-core.jar的spring.factories;

(2)GatewayClassPathWarningAutoConfiguration檢查前端控制器;

(3)網關自動配置GatewayAutoConfiguration;

(4)RoutePredicateHandlerMapping.getHandlerInternal(...)擷取Route;

(5)執行FilteringWebHandler

我們知道,傳統的Ajax請求隻能擷取在同一個域名下的資源,但是HTML5規範中打破了這種限制,允許Ajax發起跨域的請求;(隻是需要設定一下)

其實浏覽器本身是可以發起跨域請求的,比如你可以連結一個另一個域名下的圖檔或者js,比如,但是javascript腳本是不能擷取這些另一個域名下的資源内容的;

CORS是一個W3C标準,全稱是"跨域資源共享"(Cross-origin resource sharing),它允許浏覽器向跨域的另一台伺服器發出XMLHttpRequest請求,進而克服了AJAX隻能通路同域名下的資源的限制;

這種CORS使用了一個額外的HTTP響應頭來賦予目前user-agent(浏覽器)獲得跨域資源的權限,這裡的跨域也就是Cross-Origin的概念,這裡的權限就是通路另一個域名下的資源權限;

CORS是現在HTML5标準中的一部分,在大部分現代浏覽器中都有所支援,可能在某些老版本的浏覽器不支援CORS,如果要相容一些老的浏覽器版本,則需要采用JSONP進行跨域請求;

如果 通路協定、端口(如果指定了端口的話)、host都相同,則稱之為同源(不跨域),否則為非同源(跨域)

比如源連結: http://store.company.com/dir/page.html

URL

是否同源

原因

http://store.company.com/dir2/other.html

http://store.company.com/dir/inner/another.html

https://store.company.com/secure.html

協定不同

http://store.company.com:81/dir/etc.html

端口不同

http://news.company.com/dir/other.html

host不同

Spring Cloud Gateway解決跨域問題,隻需要配置如下代碼即可: