Spring
在因Netflix
開源流產事件後,在不斷的更換Netflix
相關的組件,比如:Eureka
、Zuul
、Feign
、Ribbon
等,Zuul
的替代產品就是SpringCloud Gateway
,這是Spring
團隊研發的網關組件,可以實現限流、安全認證、支持長連接等新特性。
Spring Cloud Gateway
Spring Cloud Gateway
是SpringCloud
的全新子項目,該項目基於Spring5.x
、SpringBoot2.x
技術版本進行編寫,意在提供簡單方便、可擴展的統一API路由管理方式。
概念解釋:
Route(路由)
:路由是網關的基本單元,由ID、URI、一組Predicate、一組Filter組成,根據Predicate進行匹配轉發。Predicate(謂語、斷言)
:路由轉發的判斷條件,目前SpringCloud Gateway
支持多種方式,常見如:Path
、Query
、Method
、Header
等。Filter(過濾器)
:過濾器是路由轉發請求時所經過的過濾邏輯,可用於修改請求、響應內容。
Spring Cloud GateWay 工作流程如下所示:
客戶端向Spring Cloud Gateway
發出請求。如果網關處理程序映射確定請求與路由匹配,則將其發送到網關Web處理程序。此處理程序運行時通過特定於請求的篩選鏈發送請求。過濾器被虛線分隔的原因是過濾器可以在發送代理請求之前或之後執行邏輯。執行所有“預”過濾邏輯,然後發出代理請求。在發出代理請求後,將執行“post”過濾器邏輯。
開始使用
Spring Cloud Gateway
目前有兩種方式進行配置:
application.yml
配置文件方式- 通過@Bean註解
RouteLocator
方法返回值
在本章會側重針對配置文件方式進行講解,當然RouteLocator
方式也會簡單的告訴大家的使用方式。
添加依賴
添加Spring Cloud Gateway
相關依賴,pom.xml
如下所示:
//...省略部分內容
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<!--Spring Cloud Gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
//...省略部分內容
pring Cloud Gateway Predicates
在我們開始本章內容之前我們要來先了解下Spring Cloud Gateway
內部提供的所有謂語、斷言
,這樣我們才能目標性的進行學習,我整理出來了一個腦圖,如下所示:
每一個Predicate
的使用,你可以理解爲:當滿足這種條件後纔會被轉發
,如果是多個,那就是都滿足的情況下被轉發。
Path 方式匹配轉發
通過Path
轉發示例,我們講解下上面的兩種配置,分別是application.yml
以及RouteLocator
。
配置文件匹配地址轉發
我們在application.yml
配置文件內添加對應的路由配置,如下所示:
spring:
application:
name: spring-cloud-gateway-sample
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
# 匹配路徑轉發
- Path=/api-boot-datasource-switch.html
# 端口號
server:
port: 9090
先來解釋下route
的組成部分:
id
:路由的IDuri
:匹配路由的轉發地址predicates
:配置該路由的斷言,通過PredicateDefinition
類進行接收配置。
在上面的配置中,當訪問http://localhost:9090/api-boot-datasource-switch.html
時就會被自動轉發到http://blog.yuqiyu.com/api-boot-datasource-switch.html
,這裏要注意完全匹配Path
的值時纔會進行路由轉發。
訪問效果如下所示:
RouteLocator 匹配路徑轉發
在上面的配置中,如果使用RouteLocator
方式該怎麼進行配置呢?
如下所示:
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("blog", r ->
r.path("/api-boot-datasource-switch.html").uri("http://blog.yuqiyu.com"))
.build();
}
Before 方式匹配轉發
當部署有訪問時間限制的接口時,我們可以通過Before Predicate
來完成某一個時間點之前允許訪問,過時後則不允許轉發請求到具體的服務,配置如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Before=2019-05-01T00:00:00+08:00[Asia/Shanghai]
在上面配置中,我們允許2019-05-01
日凌晨之前通過路由轉發到http://blog.yuqiyu.com
,通過查看org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory
源碼我們發現,Spring Cloud Gateway
的Before
斷言採用的ZonedDateTime
進行匹配時間,這裏要注意存在時區的問題,需要配置[Asia/Shanghai]
作爲中國時區。
After 方式匹配轉發
After Predicate
與Before
配置使用一致,匹配某一個時間點之後允許路由轉發,如下所示配置:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- After=2019-04-29T00:00:00+08:00[Asia/Shanghai]
在上面配置中允許2019-04-29
凌晨之後進行轉發到http://blog.yuqiyu.com
。
Between 方式匹配轉發
那如果是一個時間段內允許請求轉發,通過Before
、After
組合配置也可以完成,不過Spring Cloud Gateway
還是提供了Between
方式,如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Between=2019-04-29T00:00:00+08:00[Asia/Shanghai], 2019-05-01T00:00:00+08:00[Asia/Shanghai]
在上面配置中,允許在2019-04-29
日凌晨後 & 2019-05-01
凌晨之前請求轉發到http://blog.yuqiyu.com
。
Cookie 方式匹配轉發
Spring Cloud Gateway
還提供了根據Cookie
值的方式匹配轉發請求,如果請求中所攜帶的Cookie
值與配置的Predicate
匹配,那麼就可以被允許轉發到指定地址,如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Cookie=hengboy, yuqiyu
在上面配置中,如果客戶端發送請求時攜帶了"hengboy=yuqiyu"
的Cookie信息,則允許請求轉發。
測試Cookie方式轉發:
curl http://localhost:9090 --cookie "hengboy=yuqiyu"
通過上面方式我們是可以成功轉發請求的,如果我們修改Cookie
的值,就會導致無法轉發
,出現404。
Header 方式匹配轉發
Spring Cloud Gateway
可以根據發送請求的Header
信息進行匹配轉發,加入我們可以根據X-Request-Id
的值進行匹配,如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Header=X-Request-Id, \d+
在上面配置中,如果X-Request-Id
的值爲數字,那麼就可以轉發到http://blog.yuqiyu.com
,我們通過如下方式進行測試:
curl http://localhost:9090 -H "X-Request-Id:123456"
如果頭信息爲X-Request-Id:abc
時,就會轉發失敗,出現404。
Host 方式匹配轉發
Spring Cloud Gateway
可以根據Host
主機名進行匹配轉發,如果我們的接口只允許**.yuqiyu.com
域名進行訪問,那麼配置如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Host=**.yuqiyu.com
測試如下所示:
1. curl http://localhost:9090 -H "Host: yuqiyu.com" // 匹配
2. curl http://localhost:9090 -H "Host: api.yuqiyu.com" // 匹配
3. curl http://localhost:9090 -H "Host: admin.yuqiyu.com" // 匹配
3. curl http://localhost:9090 -H "Host: hengboy.com" // 不匹配
請求方式 方式匹配轉發
Rest
請求風格的接口內往往會存在多種請求方式的接口,如果我們的接口只允許POST
請求訪問,那麼配置如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Method=POST
發送GET
請求測試:
~ curl http://localhost:9090
{"timestamp":"2019-04-29T06:27:41.121+0000","path":"/","status":404,"error":"Not Found","message":null}
我們的請求並未被Spring Cloud Gateway
進行轉發,那麼我們再來通過POST
請求進行測試:
curl -X POST http://localhost:9090
是可以被轉發到目標地址uri
的,不過我的這個博客是OSS
部署的,阿里雲限制了POST
訪問,儘管如此我們也證明了可以轉發。
請求參數 方式匹配轉發
Spring Cloud GateWay
還支持根據指定的參數進行匹配,Query
方式的Predicate
也有兩種方式匹配情況,如下所示:
-
請求中存在
xxx
參數spring: cloud: gateway: routes: - id: blog uri: http://blog.yuqiyu.com predicates:
我們通過`curl http://localhost:9090\?xxx\=123`是可以被成功轉發的,只要參數存在`xxx`就會被成功轉發,否則出現404轉發失敗。
- 請求中存在`xxx`參數且值爲`zzz`
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Query=xxx, zzz
根據上面配置,我們限定了參數`xxx`必須爲`zzz`時纔會被成功轉發,否則同樣會出現404抓發失敗。
### 請求路徑 方式匹配轉發
`Spring Cloud Gateway`提供了請求路徑變量方式匹配轉發,如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Path=/article/{articleId}
在上面配置中`{articleId}`是一個路徑變量,可以是任意值,匹配`/article/1`、`/article/abc`等,測試如下所示:
~ curl http://localhost:9090/article/1 // 匹配
~ curl http://localhost:9090/article/abc // 匹配
~ curl http://localhost:9090/article/1/1 // 不匹配
### 請求IP 方式匹配轉發
`Spring Cloud Gateway`可以限制允許訪問接口的客戶端`IP`地址,配置後只對指定`IP`地址的客戶端進行請求轉發,配置如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- RemoteAddr=192.168.1.56/24
在上面我們配置了`192.168.1.56/24`,其中`192.168.1.56`是客戶端的`IP`地址,而`24`則是子網掩碼。
### 組合示例
相同的`Predicate`也可以配置多個,請求的轉發是必須滿足所有的`Predicate`後纔可以進行路由轉發,組合使用示例如下所示:
spring:
cloud:
gateway:
routes:
- id: blog
uri: http://blog.yuqiyu.com
predicates:
- Query=author, hengboy
- Query=yuqiyu
- Method=GET
- Cookie=hengboy, yuqiyu
- Header=X-Request-Id, \d+
- RemoteAddr=192.168.1.56/24
轉載:https://segmentfault.com/a/1190000019101829