在微服務架構裏,服務的粒度被進一步細分,各個業務服務能夠被獨立的設計、開發、測試、部署和管理。這時,各個獨立部署單元能夠用不一樣的開發測試團隊維護,可使用不一樣的編程語言和技術平臺進行設計,這就要求必須使用一種語言和平臺無關的服務協議做爲各個單元間的通信方式。
換句話說就是網關爲全部的請求提供了統一的入口,方便咱們對服務請求和響應作統一管理。java
API 網關是一個處於應用程序或服務(提供 REST API 接口服務)以前的系統,用來管理受權、訪問控制和流量限制等,這樣 REST API 接口服務就被 API 網關保護起來,對全部的調用者透明。正則表達式
Spring Cloud Gateway是Spring官方基於Spring 5.0,Spring Boot 2.0和Project Reactor等技術開發的網關,Spring Cloud Gateway旨在爲微服務架構提供一種簡單而有效的統一的API路由管理方式。Spring Cloud Gateway做爲Spring Cloud生態系中的網關,目標是替代ZUUL,其不只提供統一的路由方式,而且基於Filter鏈的方式提供了網關基本的功能,例如:安全,監控/埋點,和限流等。
客戶端向Spring Cloud網關發出請求。若是網關處理程序映射肯定請求與路由匹配,則將其發送到網關Web處理程序。該處理程序運行經過特定於請求的過濾器鏈發送請求。過濾器由虛線分隔的緣由是,過濾器能夠在發送代理請求以前或以後執行邏輯。執行全部「前置」過濾器邏輯,而後發出代理請求。發出代理請求後,將執行「後」過濾器邏輯。
路由和過濾器是gateway中很是重要的兩個概念,gateway自己提供了很是豐富的路由規則和多種過濾器來適配咱們的需求。gateway提供了11種路由規則,分別是:算法
該謂詞匹配在當前日期時間以後發生的請求。參數名爲 Afterspring
該謂詞匹配當前日期時間以前發生的請求。參數名爲 Before編程
該謂詞匹配在datetime1以後和datetime2以前發生的請求。參數名爲 Between安全
該謂詞匹配具備給定名稱的cookie,而且值匹配正則表達式。參數名爲 Cookiecookie
該謂詞與具備給定名稱的標頭匹配,而且值與正則表達式匹配。參數名爲 Header架構
該謂詞是指由路由進行匹配,匹配多個路由時用,隔開。參數名爲 Hostapp
該參數是一個或多個要匹配的HTTP方法。參數名爲 Method編程語言
該謂詞是指在請求路徑上加一個前綴,以此來匹配。參數名爲 Path
其中,咱們比較經常使用的就是路徑路由謂詞工廠,配合StripPrefix GatewayFilter工廠,實現咱們的路由匹配轉發。
路徑路由謂詞工廠配置以下:
spring: cloud: gateway: discovery: locator: enabled: true # 開啓從註冊中心動態建立路由的功能,利用微服務名稱進行路由 routes: # 路由id,建議配合服務名 - id: demo_route #匹配路由名 uri: lb://demo-provider predicates: # 斷言,路徑相匹配的進行路由 - Path=/demo/**
配置的含義就是,若是請求路徑中是/demo/**,則轉發到demo-provider服務。
在spring cloud gateway 2.2.2.RELEASE版本中,已經默認實現了30種過濾器。
序號 | 過濾器工廠 | 做用 | 參數 |
---|---|---|---|
1 | AddRequestHeader | 爲原始請求添加Header | Header的名稱及值 |
2 | AddRequestParameter | 爲原始請求添加請求參數 | 參數名稱及值 |
3 | AddResponseHeader | 爲原始響應添加Header | Header的名稱及值 |
4 | DedupeResponseHeader | 剔除響應頭中重複的值 | 須要去重的Header名稱及去重策略 |
5 | Hystrix | 爲路由引入Hystrix的斷路器保護 | HystrixCommand的名稱 |
6 | CircuitBreaker | 爲路由引入Resilience4J斷路器保護 | CircuitBreaker的名稱 |
7 | FallbackHeaders | 爲fallbackUri的請求頭中添加具體的異常信息 | Header的名稱 |
MapRequestHeader | 更新原始請求中的Header | Header的值 | |
9 | PrefixPath | 爲原始請求頭添加前綴 | 前綴路徑 |
10 | PreserveHostHeader | 爲請求添加preserverHostHeader=true的屬性,路由過濾器會檢查該屬性以決定是否要發送原始的host | 無 |
11 | RequestRateLimiter | 用於對請求限流,限流算法爲令牌桶 | keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus |
12 | RedirectTo | 將原始請求重定向到指定的url | http狀態碼及重定向的url |
13 | RemoveHopByHopHeadersFilter | 爲原始請求刪除IETF組織規定的一系列Header | 默認就會啓用,能夠經過配置指定僅刪除哪些Header |
14 | RemoveRequestHeader | 爲原始請求刪除某個Header | Header名稱 |
15 | RemoveResponseHeader | 爲原始響應刪除某個Header | Header名稱 |
16 | RewritePath | 重寫原始的請求路徑 | 原始路徑正則表達式以及重寫後路徑的正則表達式 |
RewriteLocationResponseHeader | 重寫響應頭的Location 的值 |
||
18 | RewriteResponseHeader | 重寫原始響應中的某個Header | Header名稱,值的正則表達式,重寫後的值 |
19 | SaveSession | 在轉發請求以前,強制執行WebSession::save 操做 |
無 |
20 | SecureHeaders | 爲原始響應添加一系列起安全做用的響應頭 | 無,支持修改這些安全響應頭的值 |
21 | SetPath | 修改原始的請求路徑 | 修改後的值 |
22 | SetRequestHeader | 修改原始請求中的某個Header的值 | Header名稱,修改後的值 |
23 | SetResponseHeader | 修改原始響應中某個Header的值 | Header名稱,修改後的值 |
24 | SetStatus | 修改原始響應的狀態碼 | HTTP 狀態碼,能夠是數字,也能夠是字符串 |
25 | StripPrefix | 用於截斷原始請求的路徑 | 使用數字表示要截斷的路徑的數量 |
26 | Retry | 針對不一樣的響應進行重試 | retries、statuses、methods、series |
27 | RequestSize | 設置容許接收最大請求包的大小。若是請求包大小超過設置的值,則返回 413 Payload Too Large 設置容許接收最大請求包的大小。若是請求包大小超過設置的值,則返回 413 Payload Too Large |
請求包大小,單位爲字節,默認值爲5M |
28 | ModifyRequestBody | 在轉發請求以前修改原始請求體內容 | 修改後的請求體內容 |
29 | ModifyResponseBody | 修改原始響應體的內容 | 修改後的響應體內容 |
30 | Default | 爲全部路由添加過濾器 | 過濾器工廠名稱及值 |
這裏比較經常使用的如第25種,配置以下:
spring: cloud: gateway: discovery: locator: enabled: true # 開啓從註冊中心動態建立路由的功能,利用微服務名稱進行路由 routes: # 路由id,建議配合服務名 - id: demo_route #匹配路由名 uri: lb://demo-provider predicates: # 斷言,路徑相匹配的進行路由 - Path=/demo/** filters: - StripPrefix=1
通常狀況下咱們配合path路由使用,這裏的意思是假如,咱們的demo-provider服務種有一個/test的接口,實際上咱們的請求路徑通過網關時應該時/demo/test,這樣就能把這個路由分發到demo-provider服務中,可是分發過去的路由是/demo/test,和咱們實際的/test接口不同。這時候咱們用StripPrefix=1,來截取掉一級路由,這樣轉發過去的路由就是/test了。
除了上面提供的30種過濾器外,咱們還能夠實現自定義的過濾器。
gatewayFilter接口是爲了實現請求過濾,ordered接口是爲了給過濾器設定優先級,值越大級別越低。
想要實現一個自定義的過濾器,無非就是兩個步驟:1.實現過濾器,2.將過濾器添加到具體路由上。
public class TokenGatewayFilter implements GatewayFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("這裏處理自身邏輯"); return chain.filter(exchange); } @Override public int getOrder() { return 0; } } @Configuration class RouteConfiguration{ @Bean public RouteLocator routeLocator(RouteLocatorBuilder builder){ return builder.routes().route( r-> r.path("/demo/**") .uri("lb://demo-provider ") .filter(new TokenGatewayFilter()) .id("demo_route ")) .build(); } }
@Component public class TokenCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenCheckGatewayFilterFactory.Config> { public TokenCheckGatewayFilterFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("enabled"); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { system.out.println("這裏處理自身邏輯") return chain.filter(exchange); }; } public static class Config { // 控制是否開啓認證 private boolean enabled = true; public Config() {} public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } } }
這裏咱們能夠直接在application.yml中爲須要過濾的路由添加這個過濾器。
spring: cloud: gateway: routes: - id: demo_route # 路由id,建議配合服務名 uri: lb://demo-provider #匹配路由名 predicates: - Path=/demo/** # 斷言,路徑相匹配的進行路由 filters: - TokenCheck=true
須要注意的是,這個地方自定義的過濾器名稱必須是XXGatewayFilterFactory,而且配置文件中配置過濾器時名字必須時這個XX。
固然,咱們也能夠爲每一個路由都添加這個過濾器,能夠直接這樣寫配置,而不用在每一個路由上都去寫。
spring: cloud: gateway: default-filters: - TokenCheck=true
這個GlobalFilter從名字中就能夠看出,是一個全局過濾器,也就是說實現這個接口後,全部的請求都會被過濾,咱們就不須要在去找往某個路由中加過濾器了。
@Component public class TokenGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("這裏處理自身邏輯"); return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
以上就是實現自定義網關過濾器的三種方式了。實際開發中根據需求來實現合適的過濾器就能夠了。