Gateway 網(wǎng)關(guān)路由、斷言、過(guò)濾
0x01: Gateway 簡(jiǎn)介
是什么?
Spring Cloud 全家桶中有個(gè)很重要的組件:網(wǎng)關(guān)。在 1.x 版本中使用的是 Zuul 網(wǎng)關(guān),但是到了 2.x,由于Zuul的升級(jí)不斷跳票,Spring Cloud 自己研發(fā)了一套網(wǎng)關(guān)組件:Spring Cloud Gateway。
Spring Cloud Gateway基于 Spring Boot 2.x,Spring WebFlux 和 Project Reactor 構(gòu)建,使用了 Webflux 中的 reactor-netty 響應(yīng)式編程組件,底層使用了 Netty 通訊框架。
詳見(jiàn):官網(wǎng)
能干嘛?
反向代理、鑒權(quán)、流量控制、熔斷、日志監(jiān)控......
網(wǎng)關(guān)在微服務(wù)架構(gòu)中的位置

0x02:Gateway 的三大概念
Route(路由):路由是構(gòu)建網(wǎng)關(guān)的基本模塊,它由 ID、目標(biāo) URI、一系列的斷言和過(guò)濾器組成,如果斷言為 true 則匹配該路由
Predicate(斷言):參考的是 Java8 中的 java.util.function.Predicate。開(kāi)發(fā)人員可以匹配 HTTP 請(qǐng)求中的所有內(nèi)容(例如請(qǐng)求頭或請(qǐng)求參數(shù)),如果請(qǐng)求與斷言相匹配則進(jìn)行路由
Filter(過(guò)濾):指的是 Spring 框架中 GatewayFilter 的實(shí)例,使用過(guò)濾器,可以在請(qǐng)求被路由之前或之后對(duì)請(qǐng)求進(jìn)行修改

0x03:工作流程

Clients make requests to Spring Cloud Gateway. If the Gateway Handler Mapping determines that a request matches a route, it is sent to the Gateway Web Handler. This handler runs the request through a filter chain that is specific to the request. The reason the filters are divided by the dotted line is that filters can run logic both before and after the proxy request is sent. All “pre” filter logic is executed. Then the proxy request is made. After the proxy request is made, the “post” filter logic is run.
翻譯:客戶端向 Spring Cloud Gateway 發(fā)出請(qǐng)求。如果網(wǎng)關(guān)處理程序映射確定請(qǐng)求與路由匹配,則將其發(fā)送到網(wǎng)關(guān) Web 處理程序。該處理程序通過(guò)特定于請(qǐng)求的過(guò)濾器鏈來(lái)運(yùn)行請(qǐng)求。 篩選器由虛線分隔的原因是,篩選器可以在發(fā)送代理請(qǐng)求之前和之后運(yùn)行邏輯。所有 “前置“ 過(guò)濾器邏輯均被執(zhí)行,然后發(fā)出代理請(qǐng)求,發(fā)出代理請(qǐng)求后,將運(yùn)行“ 后置 ”過(guò)濾器邏輯。
總結(jié):路由轉(zhuǎn)發(fā) + 執(zhí)行過(guò)濾器鏈
0x04:兩種配置方式
配置文件方式
以訪問(wèn)「百度新聞網(wǎng)」為例,添加如下配置
server:
port: 9527
spring:
application:
name: cloud-gateway9527
cloud:
gateway:
routes:
- id: news # 路由id
uri: http://news.baidu.com # 真實(shí)調(diào)用地址
predicates:
- Path=/guonei # 斷言,符合規(guī)則進(jìn)行路由
瀏覽器雖然輸入 localhost:9527/guonei,卻會(huì)轉(zhuǎn)發(fā)到指定的地址

編碼方式
新增配置文件
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("news2", r -> r.path("/guoji").uri("http://news.baidu.com"))
.build();
}
效果:

0x05:動(dòng)態(tài)路由
開(kāi)啟后,默認(rèn)情況下 Gateway 會(huì)根據(jù)注冊(cè)中心注冊(cè)的服務(wù)列表,以注冊(cè)中心上微服務(wù)名為路徑創(chuàng)建動(dòng)態(tài)路由進(jìn)行轉(zhuǎn)發(fā),從而實(shí)現(xiàn)動(dòng)態(tài)路由的功能
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #開(kāi)啟從注冊(cè)中心動(dòng)態(tài)創(chuàng)建路由的功能,利用微服務(wù)名進(jìn)行路由
routes:
- id: payment_routh1
#uri: http://localhost:8001 #靜態(tài),寫(xiě)死了地址,只能調(diào)用一個(gè)服務(wù)
uri: lb://CLOUD-PAYMENT-SERVICE #動(dòng)態(tài),lb://微服務(wù)名
predicates:
- Path=/payment/get/**
- id: payment_routh2
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/lb/**
0x06:Predicate 的使用
時(shí)間相關(guān)配置
After:在指定時(shí)間之后進(jìn)行路由
Before:在指定時(shí)間之前進(jìn)行路由
Between:在指定時(shí)間之間進(jìn)行路由
predicates:
- Path=/payment/lb/**
#- After=2020-04-25T16:30:58.215+08:00[Asia/Shanghai]
#- Before=2020-04-25T16:40:58.215+08:00[Asia/Shanghai]
- Between=2020-04-25T16:35:58.215+08:00[Asia/Shanghai],2020-04-25T16:40:58.215+08:00[Asia/Shanghai]上述配置的時(shí)間格式可以通過(guò)以下代碼得到
@Test
public void test(){
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
}
請(qǐng)求相關(guān)配置
Cookie
配置說(shuō)明:【Cookie=cookie名, cookie值的正則表達(dá)式規(guī)則】
predicates:
- Path=/payment/lb/**
- Cookie=id, [0-9使用 curl 工具模擬攜帶 cookie 發(fā)送請(qǐng)求

Header
配置說(shuō)明:【Header=header名, header值的正則表達(dá)式規(guī)則】
predicates:
- Path=/payment/lb/**
- Header=h, [a-h]

Host
配置說(shuō)明:【Host=主機(jī)名(可配置多個(gè),也可以使用通配符)】
predicates:
- Path=/payment/lb/**
- Host=**.a.com,**.b.cn

Method
配置說(shuō)明:【Method=請(qǐng)求類(lèi)型】
predicates:
- Path=/payment/lb/**
- Method=GET

Path
配置說(shuō)明:【Path=請(qǐng)求路徑】
predicates:
- Path=/payment/lb/**

Query
配置說(shuō)明:【Query=參數(shù)名,參數(shù)值】
predicates:
- Path=/payment/lb/**
- Query=name, zhangsan

詳見(jiàn):官網(wǎng)
0x07:Filter 的使用
生命周期:pre、post
種類(lèi):GatewayFilter、GlobalFilter
GatewayFilter 在官方文檔有幾十種!詳細(xì)配置可參考 官網(wǎng),這里主要介紹自定義全局過(guò)濾器。
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String username = exchange.getRequest().getQueryParams().getFirst("username");
//用戶名為空時(shí),給出錯(cuò)誤響應(yīng)
if (username == null) {
log.info("用戶名為空,非法登錄");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}


source:https://www.cnblogs.com/songjilong/p/12774265.html
喜歡,在看
