原文:
blog.csdn.net/Cristiano272/article/details/131814765
1、網關介紹
如果沒有網關,難道不行嗎?功能上是可以的,我們直接調用提供的接口就可以了。那為什麼還需要網關?
因為網關的作用不僅僅是轉發請求而已。我們可以試想一下,如果需要做一個請求認證功能,我們可以接入到 API 服務中。但是倘若後續又有服務需要接入,我們又需要重複接入。這樣我們不僅代碼要重複編寫,而且後期也不利于維護。
由于接入網關後,網關将轉發請求。是以在這一層做請求認證,天然合适。這樣這需要編寫一次代碼,在這一層過濾完畢,再轉發給下面的 API。
是以 API 網關的通常作用是完成一些通用的功能,如請求認證,請求記錄,請求限流,黑白名單判斷等。
API網關是一個伺服器,是系統的唯一入口。
API網關方式的核心要點是,所有的用戶端和消費端都通過統一的網關接入微服務,在網關層處理所有的非業務功能。通常,網關提供REST/HTTP的通路API。
2、Spring Cloud Gateway介紹
Spring Cloud Gateway是Spring Cloud的新一代API網關,基于WebFlux架構實作,它旨在為微服務架構提供一種簡單而有效的統一的API路由管理方式。
Spring Cloud Gateway作為Spring Cloud生态系統中的網關,目标是替代Netflix ZUUL,具有更好的性能、更強的擴充性、以及更豐富的功能特性,其不僅提供統一的路由方式,并且基于Filter鍊的方式提供了網關基本的功能,例如:安全,監控/埋點,限流等。
3、Spring Cloud Gateway的特性
- 基于Spring Framework 5, Project Reactor和Spring Boot 2.0
- 動态路由:能夠比對任何請求屬性
- 可以對路由指定 Predicate 和 Filter
- 內建Hystrix斷路器
- 內建Spring Cloud DiscoveryClient 服務發現功能
- 易于編寫的Predicate和Filter
- 請求限流
- 支援路徑重寫
4、Spring Cloud Gateway的三大核心概念
路由(Route): 路由是網關最基礎的部分,路由資訊由一個ID,一個目标URI,一組斷言和過濾器組成。路由斷言Predicate用于比對請求,過濾器Filter用于修改請求和響應。如果斷言為true,則說明請求URI和配置比對,則執行路由。
spring:
cloud:
gateway:
# 定義多個路由
routes:
# 一個路由route的id
- id: path_route
# 該路由轉發的目标URI
uri: https://example.org
# 路由條件集合
predicates:
- Path=/test/**
# 過濾器集合
filters:
- AddRequestHeader=X-Request-Id, 1024
- AddRequestParameter=color, red
斷言(Predicate): 參考Java8中的斷言Predicate,用于實作請求比對邏輯,例如比對路徑、請求頭、請求參數等。請求與斷言比對則執行該路由。
過濾器(Filter): 指的是Spring架構中GatewayFilter的執行個體,使用過濾器,可以在請求被路由前後對請求進行修改。
5、Gateway工作流程
用戶端向Spring Cloud Gateway送出請求,然後在Gateway Handler Mapping中找到與請求相比對的路由,将其發送到Gateway Web Handler。Handler再通過指定的過濾器鍊來對請求進行過濾處理,最後發送到我們實際的服務執行業務邏輯,然後傳回。
過濾器鍊被虛線分隔,是因為過濾器既可以在轉發請求前攔截請求,也可以在請求處理之後對響應進行攔截處理。
6、Gateway核心配置
依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
啟動類
@SpringBootApplication
@EnableEurekaClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
application.yml
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
# 路由的ID,沒有固定規則但要求唯一,建議配合服務名
- id: config_route
# 比對後提供服務的路由位址
uri: http://ityouknow.com
# 斷言,路徑相比對的條件
predicates:
- Path=/routeconfig/rest/**
- id: header_route
uri: http://ityouknow.com
predicates:
- Header=X-Request-Id, \d+
7、動态路由
網關接收外部請求,按照一定的規則,将請求轉發給其他服務或者應用。如果站在服務調用的角度,網關就扮演着服務消費者的角色,此時,如果再來看看服務調用的目标URI配置,就會很自然的發現一個問題,服務提供者調用的位址是寫死的,即網關沒有動态的發現服務,這就涉及到了服務的自動發現問題,以及發現服務後,所涉及到的服務調用的負載均衡的問題。
可以通過Nacos或者Eureka注冊中心動态發現服務,通過Ribbon進行服務調用的負載均衡。同樣,Gateway也可以整合Nacos或者Eureka,Ribbon進而實作動态路由的功能。
想要使用動态路由的功能,首先要整合注冊中心,這裡以Nacos為例
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
spring:
application:
name: cloud-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
#路由的ID,沒有固定規則但要求唯一,建議配合服務名
- id: config_route
#比對後提供服務的路由位址, 這裡lb之後,跟的是要調用的服務名稱
uri: lb://nacos-provider-8002
# 斷言,路徑相比對的條件
predicates:
- Path=/routeconfig/rest/**
此時,當id為config_route的路由規則比對某個請求後,在調用該請求對應的服務時,就會從nacos注冊中心自動發現服務,并在服務調用的時候實作負載均衡。
8、Predicate
在Gateway中,有一些的内置Predicate Factory,有了這些Pridicate Factory,在運作時,Gateway會 自動根據需要建立其對應的Pridicate對象測試路由條件。
Path 路由斷言 Factory: 根據請求路徑比對的路由條件工廠
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
# 如果可以比對的PathPattern有多個,則每個路徑模式以,分開
- Path=/red/{segment},/blue/{segment}
After 路由斷言 Factory: 在指定日期時間之後發生的請求都将被比對
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
Cookie 路由斷言 Factory: Cookie 路由斷言 Factory有兩個參數,cookie名稱和正規表達式。請求包含此cookie名稱且正規表達式為真的将會被比對。
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
Header 路由斷言 Factory: Header 路由斷言 Factory有兩個參數,header名稱和正規表達式。請求包含此header名稱且正規表達式為真的将會被比對。
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
Host 路由斷言 Factory: Host 路由斷言 Factory包括一個參數:host name清單。使用Ant路徑比對規則, . 作為分隔符。
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
Method 路由斷言 Factory: Method 路由斷言 Factory隻包含一個參數:需要比對的HTTP請求方式
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET
自定義Predicate
可以自定義Predicate來實作複雜的路由比對規則:
// 實作自定義 Predicate 工廠
// 通過HostRoutePredicateFactory建立Predicate進行路由判斷
@Component
public class MyHostRoutePredicateFactory extends AbstractRoutePredicateFactory<MyHostRoutePredicateFactory.Config> {
public MyHostRoutePredicateFactory() {
// Config 類作為 Predicate 的配置參數類
super(Config.class);
}
public static class Config {
// 路由比對規則
private String hostName;
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
}
// 生成一個 Predicate 執行個體
@Override
public Predicate<ServerWebExchange> apply(Config config) {
// 實作比對邏輯
return exchange -> {
// 根據config實作比對判斷
String host = exchange.getRequest().getURI().getHost();
// 比對配置中的域名
return host.equals(config.getHostName());
};
}
}
// 使用
RouteLocator locator = new RouteLocatorBuilder(router)
.routes()
.route("test_route", r -> r.path("/test")
.filters(f -> f.filter(new MyHostRoutePredicateFactory.Config("www.test.com")))
.uri("http://localhost:8080"))
.build();
9、自定義Filter
可以通過實作GatewayFilter和Ordered接口自定義Filter來實作請求處理邏輯:
@Component
public class TokenFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//請求處理邏輯
log.info("請求路徑:"+ exchange.getRequest().getPath());
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, HttpCookie> cookies = request.getCookies();
List<HttpCookie> tokens = cookies.get("access_token");
if (tokens == null || tokens.size() == 0) {
throw new RuntimeException("少了cookie!");
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
10、預設過濾器
Spring Cloud Gateway内置了多種過濾器,例如:
- AddRequestHeader GatewayFilter:在請求頭中添加參數
- PrefixPath GatewayFilter:請求路徑字首
- Hystrix GatewayFilter: 斷路器
- RateLimit GatewayFilter: 限流
- Retry GatewayFilter: 重試