一、需求
記錄Spring Cloud Gateway的一些用法,不對其原理進行過多的探究。
二、基本組成
1、簡介
Spring Cloud Gateway 是 基于Spring boot 5、Spring Boot 2.0和Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān)。它旨在為微服務(wù)提供一個簡單有效的方式來管理api路由。
Spring Cloud Gateway 是基于 Netty 運行的,不能運行在傳統(tǒng)的Servlet容器中作為War包運行。
2、核型概念
1、Route 路由
Route是網(wǎng)關(guān)的基本組成單元,它是有一個ID,一個目標(biāo)URI和一組predicates和一組filters組成,如果一組斷言結(jié)果為真,則匹配路由,目標(biāo)URI會被訪問。
注意:
1、多個 Predicate 之間是 邏輯and 的關(guān)系。
2、多個Predicate是從定義的順序從上到下依次執(zhí)行,也可以指定 order 屬性的值。
2、Predicate 謂語、斷言
Predicate 是Java 8 Function interface。輸入類型是Spring Framework ServerWebExchange??梢杂脕砥ヅ?code>HTTP請求中的任何內(nèi)容,例如headers 或者 parameters。
3、Filter 過濾器
Filter是GatewayFilter的實例。通過Filter我們可以在請求發(fā)送或返回下游服務(wù)時 修改 請求和響應(yīng)。
3、工作原理

上圖來自 Spring 官網(wǎng)。
三、網(wǎng)關(guān) Predicate配置方式
1、快捷配置方式(配置文件)
快捷方式是由過濾器是的名稱識別,后面緊跟=,在跟以逗號(,)分隔的參數(shù)值。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Cookie=mycookie,mycookievalue
上一個示例使用兩個參數(shù)定義了Cookie Route Predicate Factory,這兩個參數(shù)是cookie名稱,mycookie和與mycookievalue匹配的值
2、完全展開的參數(shù)(配置文件)
name:指定謂詞工廠的名字
args:指定對應(yīng)謂詞工廠中的參數(shù)對應(yīng)的值。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
這種方式配置和上面的快捷方式配置的是一個意思
3、上方2種方式配置和代碼對應(yīng)關(guān)系
4、uri 值的方式
1、以http開頭
當(dāng)匹配到這個路由后,會跳轉(zhuǎn)到這個地址。
2、以 lb 開頭
eg:
?????uri: lb://service-name
解釋:
lb:表示負(fù)載均衡的意思
service-name:值的是調(diào)用服務(wù)在注冊中心注冊的服務(wù)名。
四、Route Predicate Factories
Spring Cloud Gateway內(nèi)置了特別多的路由謂詞工廠,用來匹配http請求。當(dāng)多個一起使用時,是and的關(guān)系,即需要所有的謂詞工廠都匹配,才匹配這個路由。
1、After
1、描述:
當(dāng)前請求在指定時間之后才匹配
2、存在參數(shù):
????datetime 數(shù)據(jù)類型是 ZonedDateTime,帶有時區(qū)
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- After=2020-11-01T11:05:08.020+08:00[Asia/Shanghai]
2、Before
1、描述:
當(dāng)前請求在指定時間之前才匹配
2、存在參數(shù):
????datetime 數(shù)據(jù)類型是 ZonedDateTime,帶有時區(qū)
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Before=2020-11-01T11:05:08.020+08:00[Asia/Shanghai]
3、Between
1、描述:
當(dāng)前請求在指定時間中間才匹配
2、存在參數(shù):
????datetime1 數(shù)據(jù)類型是 ZonedDateTime,帶有時區(qū)
????datetime2 數(shù)據(jù)類型是 ZonedDateTime,帶有時區(qū)
???? 并且 datetime1 必須< datetime2
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Between=2020-11-01T11:08:08.020+08:00[Asia/Shanghai],2020-11-01T11:15:08.020+08:00[Asia/Shanghai]
4、Cookie
1、描述:
當(dāng)前請求中的cookie值匹配配置的cookie參數(shù)值時生效
2、存在參數(shù):
????name 請求cookie中的參數(shù)的名字
????regexp 請求cookie中的參數(shù)的值,配置的值是Java中的正則表達式形式。
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Cookie=token,tokenvalue\d+

4、解釋
- Cookie=token,tokenvalue\d+
表示 請求中必須存在一個 cookie 的key 是 token 的,且值必須是tokenvalue 后面加上一個數(shù)子才匹配的上,否則匹配不上。
5、Header
1、描述:
當(dāng)前請求中的header值匹配配置的header參數(shù)值時生效
2、存在參數(shù):
????name header key的名字
????regexp header key對應(yīng)的值,配置的值是Java中的正則表達式形式。
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Header=X-Token-Id,\d+
4、解釋
- Header=X-Token-Id,\d+
表示請求頭中必須存在R-Token-Id且它的值必須是數(shù)字
6、Host
1、描述:
匹配請求頭中的Host的值
2、存在參數(shù):
????patterns 配置一系列的以.作為分隔的ant風(fēng)格host地址,多個中間以,隔開。Host中配置的值還支持URI template variables,比如{xxx}.baidu.com
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Host=**.gateway.com,{study}.baidu.com
4、解釋
- Host=**.gateway.com,{study}.baidu.com
1、**.gateway.com:表示請求中的Host的值需要配置這種ant風(fēng)格
2、{study}.baidu.com:study這個模版變量可以在GatewayFilter中獲取到,通過ServerWebExchange.getAttributes().get(ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE)獲取
7、Method
1、描述:
匹配請求頭中的Method的值
2、存在參數(shù):
????methods 需要匹配的方法,比如GET、POST等
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Method=GET,POST,PUT # 只有g(shù)et,post,put請求才能匹配上方這個路由
8、Path
1、描述:
匹配請求路徑。
2、存在參數(shù):
????patterns 需要匹配的路徑eg: /product/{id},/product/**
????matchOptionalTrailingSeparator 一個可選的參數(shù)
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- Path=/product/findOne/{productId},/product/**
4、解釋
/product/findOne/{productId} 支持uri模版變量,productId可以在GatewayFilter中獲取,獲取方式.
Map<string, string> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("productId");
9、Query
1、描述:
匹配請求參數(shù)。
2、存在參數(shù):
????param 請求參數(shù)的key值
????regexp 請求參數(shù)的值,配置的值是Java中的正則表達式形式。
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
#- Query=pwd
- Query=username,\d+
4、解釋
1、Query=pwd 表示請求中必須存在 pwd這個請求參數(shù)
2、Query=username,\d+ 表示請求中必須存在username這個參數(shù),且它的值必須是數(shù)字
10、RemoteAddr
1、描述:
匹配請求的ip地址,支持ipv4和ipv6。
2、存在參數(shù):
????sources 地址列表eg:127.0.0.1/16 后方的/16是子網(wǎng)掩碼
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider # 名字唯一即可
uri: lb://product-provider
predicates:
- RemoteAddr=127.0.0.1/16
4、注意
如果我們的Spring Cloud Gateway是位于代理后面,那么獲取到遠(yuǎn)程地址可能不正確,此時我們可以自己編寫一個RemoteAddressResolver來解決。
11、Weight
1、描述:
根據(jù)權(quán)重來分發(fā)請求,權(quán)重是根據(jù)group來計算的。
2、存在參數(shù):
????group 組,權(quán)重根據(jù)組來計算
????weight 權(quán)重值,是一個 Int 的值
3、配置實例
spring:
cloud:
gateway:
routes:
- id: product-provider
uri: https://weighthigh.org
predicates:
- Weight=group1,8
- id: user-consumer
uri: https://weightlow.org
predicates:
- Weight=group1,2
4、解釋
上方配置會導(dǎo)致80%的請求落到 https://weighthigh.org,有20%的請求落到https://weightlow.org
五、自己編寫一個 route predicate factory
1、編寫步驟
1、編寫一個類,實現(xiàn)RoutePredicateFactory接口,或繼承AbstractRoutePredicateFactory
????> 1、AbstractRoutePredicateFactory<c> 中的 C 表示 配置文件類
????> 2、重寫shortcutFieldOrder此方法,表示的配置文件中參數(shù)的位置
????> 3、重寫apply(C c)方法,表示的是具體的業(yè)務(wù)邏輯
2、我們自己編寫的類必須要以RoutePredicateFactory結(jié)尾,否則比較麻煩,參考
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#initFactories 這個方法。
2、要實現(xiàn)的功能
判斷請求參數(shù)中是否存在 token 配置的值。
3、Java代碼
@Slf4j
@Component
public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<tokenroutepredicatefactory.config> {
public TokenRoutePredicateFactory() {
super(Config.class);
}
@Override
public List<string> shortcutFieldOrder() {
return Lists.newArrayList("token");
}
@Override
public Predicate<serverwebexchange> apply(Config config) {
return exchange -> {
log.info("判斷請求頭中是否存在token這個參數(shù)");
String token = exchange.getRequest().getQueryParams().getFirst(config.getToken());
return StringUtils.isNotBlank(token);
};
}
@Data
public static class Config {
private String token;
}
}
4、配置文件
spring:
cloud:
gateway:
routes:
- id: product-provider
uri: lb://product-provider
predicates:
- Token=token
5、解釋
六、完整代碼
https://gitee.com/huan1993/spring-cloud-alibaba-parent/tree/master/gateway
七、參考鏈接
https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/