在微服務架構中,我們會遇到這樣的問題:1.在調用微服務時,需要鑒權,微服務不能任意給外部調用。但是,多個微服務如果都需要同一套鑒權規則,明顯會產生冗余,如果鑒權方法需要修改,則需要改動多個地方。2.在前端調用服務的時候,前端需要根據不同的服務配置,找到對於服務的IP,端口等信息,才能完成對應調用。如果中間有修改或者有擴展時,這會顯得很麻煩,尤其是在微服務越來越多的時候。
有沒有一種方式,提供一個統一的入口,統一鑒權,配置路由,解決上面兩個問題?Spring Cloud Gateway為我們提供了很好的解決方案。在Finchley版本之前,Spring Cloud使用netflix的Zuul完成類似的功能。在Finchley之后,我們更推薦使用Spring Cloud自行開發的Gateway,Gateway對比Zuul 1.0具有更好的性能和集成性。
該項目提供了一個建立在Spring Ecosystem之上的API網關,包括:Spring 5,Spring Boot 2和Project Reactor。Spring Cloud Gateway旨在提供一種簡單而有效的方式來路由到API,並為他們提供橫切關注點,例如:安全性,監控/指標和彈性。
01.配置使用
添加gateway依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
02.工作流程

客戶端向Spring Cloud Gateway發出請求。如果網關處理程序映射確定請求與路由匹配,則將其發送到網關Web處理程序。此處理程序運行通過特定於請求的過濾器鏈發送請求。濾波器被虛線划分的原因是濾波器可以在發送代理請求之前或之后執行邏輯。執行所有“預”過濾器邏輯,然后進行代理請求。在發出代理請求之后,執行“post”過濾器邏輯。
03.詳細配置
1.路由謂詞工廠(具體的配置和說明已注釋到代碼中)
spring: application: name: gateway-service cloud: gateway: routes: #指定時間前的路由地址 - id: before_route uri: http://www.baidu.com predicates: - Before=2017-01-20T17:42:47.789-07:00 #指定時間之間的路由地址 - id: before_route uri: http://www.sohu.com predicates: - Between=2020-01-20T17:42:47.789-07:00,2020-01-21T17:42:47.789-07:00 #指定時間后的路由地址 - id: before_route uri: http://www.sina.com predicates: - After=2019-05-20T17:42:47.789-07:00 #指定Cookie中有指定值的路由地址,這里注意有兩個參數,第一個為Cookie的Key,第二個為正則表達式 - id: cookie_route uri: http://www.qq.com predicates: - Cookie=chocolate,[A-Za-z]+ #指定Header中有指定值的路由地址,有兩個參數,第一個為Header的Key,第二個為正則表達式 - id: header_route uri: http://www.163.com predicates: - Header=X-Request-Id, \d+ #指定Host的路由 - id: host_route uri: http://www.360.com predicates: - Host=**.somehost.org,**.anotherhost.org #指定請求方法的路由 - id: method_route uri: http://www.baidu.com predicates: - Method=GET #segment作為參數,可以在接口后台獲取 - id: params_route uri: lb://test-client-service predicates: - Path=/test/{segment} filters: #SetPath filter 使用模版參數,修改請求路徑 - SetPath=/{segment} #AddRequestHeader過濾器添加Request頭 - AddRequestHeader=X-Request-Foo, Bar #ip地址控制路由,192.168.1.1 - id: remoteaddr_route uri: http://localhost:8090 predicates: - RemoteAddr=192.168.1.1 #url中帶有params查詢的,如:http://localhost:9005/getUser?params=111,params后還可以加正則表達式,如:params,\d+ - id: query_route uri: lb://test-client-service predicates: - Query=params
2.過濾工廠
路由過濾器允許以某種方式修改傳入的HTTP請求或傳出的HTTP響應,路徑過濾器的范圍限定為特定路徑。
#以下為過濾工廠,過濾工廠與謂詞工廠同級 filters: #AddRequestHeader過濾器添加Request頭 - AddRequestHeader=X-Request-Foo, Bar #AddRequestParameter過濾器添加參數頭 - AddRequestParameter=bar, barValue #AddResponseHeader過濾器添加返回Response頭 - AddResponseHeader=X-Response-Foo, 123 #PrefixPath添加前綴,如請求為/getUser,則會轉成/mypath/getUser #- PrefixPath=/mypath #往exchange添加PRESERVE_HOST_HEADER_ATTRIBUTE - PreserveHostHeader #結合redis限流 #redis-rate-limiter.replenishRate:允許用戶每秒處理多少個請求 #redis-rate-limiter.burstCapacity:令牌桶的容量,允許在一秒鍾內完成的最大請求數 - name: RequestRateLimiter args: key-resolver: "#{@remoteAddrKeyResolver}" redis-rate-limiter.replenishRate: 1 redis-rate-limiter.burstCapacity: 5 #RedirectTo 重定向,第一個參數是狀態碼,必須是3xx,第二個參數是要重定向的地址 #- RedirectTo=302, http://www.baidu.com #刪除NonProxy頭信息,默認刪除 #Connection #Keep-Alive #Proxy-Authenticate #Proxy-Authorization #TE #Trailer #Transfer-Encoding #Upgrade #可以通過spring.cloud.gateway.filter.remove-non-proxy-headers.headers配置要刪除得到頭信息 - RemoveNonProxyHeaders #RemoveRequestHeader 刪除指定頭信息filter - RemoveRequestHeader=X-Request-Foo #RemoveResponseHeader 刪除返回頭信息filter - RemoveResponseHeader=X-Response-Foo #RewritePath過濾工廠,下面這個寫法的意思是把請求都帶上前綴/foo,如請求是/example,則真正到達后台的請求會變成/foo/example - RewritePath=/(?<segment>.*), /foo/$\{segment} #RewriteResponseHeader 重寫ResponseHeader,三個參數,第一個是頭的key值,第二個是需要替換的值,第三個是替換后的值,其中第二個參數可以使用正則表達式來匹配 - RewriteResponseHeader=X-Response-Foo, 123, 321 #SaveSession 會話保存過濾器 - SaveSession #SecureHeaders 默認往返回的response添加以下header,可以通過配置spring.cloud.gateway.filter.secure-headers 修改需要添加的header # X-Xss-Protection:1; mode=block # Strict-Transport-Security:max-age=631138519 # X-Frame-Options:DENY # X-Content-Type-Options:nosniff # Referrer-Policy:no-referrer # Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline' # X-Download-Options:noopen # X-Permitted-Cross-Domain-Policies:none - SecureHeaders #SetResponseHeader ,修改responseHeader - SetResponseHeader=X-Response-Foo1, modifyValue #SetStatus 設置返回的狀態,可以是code(如404,401,403),也可以是對應的描述(注意描述中間的空格要用下划線替換) - SetStatus=BAD_GATEWAY #StripPrefix 除去請求的前X位,如X是2且請求是/1/2/3,則最終請求是/3,如X是2且請求是/1,則最終請求是/ - StripPrefix=0 #Retry 重試機制 #retries,默認為3,用來標識重試次數 #series,用來指定哪些段的狀態碼需要重試,默認SERVER_ERROR即5xx #statuses,用於指定哪些狀態需要重試,默認為空,它跟series至少得指定一個 #methods,用於指定那些方法的請求需要重試,默認為GET #exceptions,用於指定哪些異常需要重試,默認為java.io.IOException - name: Retry args: retries: 3 series: - SERVER_ERROR methods: - GET - POST exceptions: - java.lang.RuntimeException # RequestSize 請求最大size - name: RequestSize args: maxSize: 1000
3.Hystrix過濾工廠
Hystrix是Netflix的一個庫,它實現了斷路器模式。Hystrix GatewayFilter允許您將斷路器引入網關路由,保護您的服務免受級聯故障的影響,並允許您在下游故障時提供回退響應。
#Hystrix gateway過濾器工廠,需要引入hystrix包,當請求服務超時時,請求gateway本地的fallback接口 - name: Hystrix args: name: fallbackcmd fallbackUri: forward:/fallback - id: ingredients-fallback uri: lb://hystrix-service predicates: - Path=/fallback filters: - name: FallbackHeaders args: executionExceptionTypeHeaderName: Test-Header #此配置可配置gateway請求的超時時間 #hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000 - Hystrix=testHystrixExtendsCommandService
轉自:https://www.jianshu.com/p/dabf2d91fd6e