文章目錄
一、Gateway介紹
1. Getway簡介
由於Netflix
在zull
、zull2
的推出出現問題,SpringCloud
推出了自己的網關GeteWay
。
SpringCloud Gateway
是Spring Cloud
的一個全新項目,基於Spring 5.0
+Spring Boot 2.0
和Project Reactor
等技術開發的網關,它旨在爲微服務架構提供一種簡單有效的統一的API
路由管理方式。
SpringCloud Gateway
作爲Spring Cloud
生態系統中的網關,目標是替代Zuul
,在Spring Cloud 2.0
以上版本中,沒有對新版本的Zuul 2.0
以上最新高性能版本進行集成,仍然還是使用的Zuul 1.x
非Reactor
模式的老版本。而爲了提升網關的性能,SpringCloud Gateway
是基於WebFlux
框架實現的,而WebFlux
框架底層則使用了高性能的Reactor
模式通信框架Netty
。
Spring Cloud Gateway
的目標提供統一的路由方式且基於Filter
鏈的方式提供了網關基本的功能,例如:安全、監控/指標、和限流。
2. Gateway作用
①反向代理
②鑑權
③流量控制
④熔斷
⑤日誌監控
3. 三大核心概念
①Route(路由)
路由是構建網關的基本模塊,它由ID
,目標URI
,一系列的斷言和過濾器組成,如果斷言爲true
則匹配該路由。
②Predicate(斷言)
參考java8
的java.util.function.Predicate
開發人員可以匹配HTTP
請求中的所有內容(例如請求頭和請求參數),如果請求與斷言相匹配則進行路由。
③Filter(過濾)
指的是Spring
框架中GatewayFilter
的實例,使用過濾器,可以在請求被路由前或之後對請求進行修改。
web
請求通過一些匹配條件,定位到真正的服務節點,並在這個轉發過程的前後,進行一些細化控制。
pridicate
就是我們的匹配條件;而filter
,就可以理解爲一個無所不能的攔截器。有了這兩個元素,再加上目標url
,就可以實現一個具體的路由了。
4.Gateway流程
客戶端向Spring Cloud Gateway
發出請求。然後在Gateway Handler Mapping
中找到與請求相匹配的路由,將其發送到GatewayWeb Handler
。
Handler
再通過指定的過濾器鏈來將請求發送到我們實際的服務執行業務邏輯,然後返回。
過濾器之間用虛線分開是因爲過濾器可能會在發送代理請求之前( “pre” )或之後( “post” )執行業務邏輯。
Filter
在pre
類型的過濾器可以做參數校驗、權限校驗、流量監控、日誌輸出、協議轉換等,在post
類型的過濾器中可以做響應內容、響應頭的修改,日誌的輸出,流量監控等有着非常重要的作用。
核心邏輯:路由轉發+執行過濾器鏈
二、Gateway的使用
1. 入門
①新建一個項目cloud-gateway9527
,添加Gateway
的依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
②我們不想暴露8001項目的端口,因此在9527做路由映射,有兩種路由映射方式:
③yml配置
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 開啓從註冊中心動態創建路由的功能,利用微服務名稱進行路由
routes:
- id: payment_route # 路由的id,沒有規定規則但要求唯一,建議配合服務名
#匹配後提供服務的路由地址
uri: http://localhost:8001
predicates:
- Path=/payment/discovery/** # 斷言,路徑相匹配的進行路由
④編碼
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
RouteLocatorBuilder.Builder routes = builder.routes();
routes.route("/payment_route2",
route -> route.path("/payment/discovery/**")
.uri("http://localhost:8001")
);
return routes.build();
}
}
⑤經測試,這兩種方式均可行:
2. 通過微服務名實現動態路由
默認情況下Gateway
會根據註冊中心的服務列表,以註冊中心上微服務名爲路徑創建動態路由進行轉發,從而實現動態路由的功能。
需要注意的是uri
的協議爲lb
,表示啓用Gateway
的負載均衡功能。修改uri
即可:
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 開啓從註冊中心動態創建路由的功能,利用微服務名稱進行路由
routes:
- id: payment_route # 路由的id,沒有規定規則但要求唯一,建議配合服務名
#lb://微服務名
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/discovery/** # 斷言,路徑相匹配的進行路由
3.Predicate的使用
Spring Cloud Gateway
將路由匹配作爲Spring WebFlux HandlerMapping
基礎架構的一部分。
Spring Cloud Gateway
包括許多內置的Route Predicate
工廠,如下圖。所有這些Predicate
都與HTTP
請求的不同屬性匹配。多個Route Predicate
工廠可以進行組合。
Spring Cloud Gateway
創建Route
對象時,使用Route Predicate Factory
創建Predicate
對象,Predicate
對象可以賦值給Route
。所有的 Route Predicate
都對應着HTTP
請求的不同屬性。可以通過and
相互組合。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7mlP0Yk0-1587129412752)(D:\MyNote\img\Predicate的使用.png)]
常用的Route Predicate Factory
:
①After/Before/Between
設置請求生效時間/失效時間,時間格式爲java8
新出的java.time.ZonedDateTime
。
...
predicates:
- Path=/payment/discovery/** #路徑相匹配的進行路由
- After=2020-04-17T20:28:54.492+08:00[Asia/Shanghai]
#- Before=2020-04-17T20:28:54.492+08:00[Asia/Shanghai]
#- Between=2020-04-16T20:28:54.492+08:00[Asia/Shanghai], 2020-04-17T20:28:54.492+08:00[Asia/Shanghai]
②Cookie/Header/HOST
Cookie Route Predicate
需要兩個參數, 一個是Cookie name
,一個是正則表達式。路由規則通過獲取對應的Cookie name
值和正則表達式去匹配。
路由規則通過Header
去匹配。
路由規則通過Host
去匹配。
...
predicates:
- Path=/payment/discovery/**
- Cookie=username,zzyy
- Header=X-Request-Id, \d+ #請求頭要有X-Request-Id屬性,並且值爲正數
- Host=**.ctj.com
其他Route Predicate Factory
參考官網。
總結:Predicate
就是爲了實現一組匹配原則,讓請求過來找到對應的Route
進行處理
4.Filter的使用
路由過濾器可用於修改進入的HTTP
請求和返回的HTTP
響應,路由過濾器只能指定路由進行使用。
Spring Cloud Gateway
內置了多種路由過濾器,他們都由GatewayFilter
的工廠 類來產生。其生命週期有兩種:pre
(業務邏輯執行之前)和post
(業務邏輯執行之後)。種類有兩種:GatewayFilter
和GlobalFilter
。
使用GatewayFilter
:
例:該AddRequestHeader
GatewayFilter
工廠需要name
和value
參數。它將X-Request-red:blue
標頭添加到所有匹配請求的下游請求的標頭中。
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
具體參考官網:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/
①自定義GlobalFilter
作用:1、全局日誌記錄
2、統一網關鑑權,可以結合Spring Security
完成對用戶的認證授權
用戶校驗實現代碼:
@Component
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("******用戶驗證開始: " + new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
if(uname == null) {
log.info("******非法用戶******");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
log.info("******用戶驗證成功******");
return chain.filter(exchange);
}
/**
* 加載過濾器的順序,數據越小,優先級越高
* @return int
*/
@Override
public int getOrder() {
return 0;
}
}
訪問http://localhost:9527/payment/discovery
日誌打印,請求並且被攔截:
訪問http://localhost:9527/payment/discovery?uname=a
日誌打印,請求被放行: