1.網關介紹 如果沒有網關,難道不行嗎?功能上是可以的,我們直接調用提供的介面就可以了。那為什麼還需要網關? 因為網關的作用不僅僅是轉發請求而已。我們可以試想一下,如果需要做一個請求認證功能,我們可以接入到 API 服務中。但是倘若後續又有服務需要接入,我們又需要重覆接入。這樣我們不僅代碼要重覆編寫 ...
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再通過指定的過濾器鏈來對請求進行過濾處理,最後發送到我們實際的服務執行業務邏輯,然後返回。
過濾器鏈被虛線分隔,是因為過濾器既可以在轉發請求前攔截請求,也可以在請求處理之後對響應進行攔截處理。
推薦一個開源免費的 Spring Boot 實戰項目:
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
: 重試
來源:blog.csdn.net/Cristiano272/article/details/131814765
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!