1.網(wǎng)關介紹
如果沒有網(wǎng)關,難道不行嗎?功能上是可以的,我們直接調用提供的接口就可以了。那為什么還需要網(wǎng)關?
因為網(wǎng)關的作用不僅僅是轉發(fā)請求而已。我們可以試想一下,如果需要做一個請求認證功能,我們可以接入到 API 服務中。但是倘若后續(xù)又有服務需要接入,我們又需要重復接入。這樣我們不僅代碼要重復編寫,而且后期也不利于維護。
由于接入網(wǎng)關后,網(wǎng)關將轉發(fā)請求。所以在這一層做請求認證,天然合適。這樣這需要編寫一次代碼,在這一層過濾完畢,再轉發(fā)給下面的 API。
所以 API 網(wǎng)關的通常作用是完成一些通用的功能,如請求認證,請求記錄,請求限流,黑白名單判斷等。
API網(wǎng)關是一個服務器,是系統(tǒng)的唯一入口。
API網(wǎng)關方式的核心要點是,所有的客戶端和消費端都通過統(tǒng)一的網(wǎng)關接入微服務,在網(wǎng)關層處理所有的非業(yè)務功能。通常,網(wǎng)關提供REST/HTTP的訪問API。
2.Spring Cloud Gateway介紹
Spring Cloud Gateway是Spring Cloud的新一代API網(wǎng)關,基于WebFlux框架實現(xiàn),它旨在為微服務架構提供一種簡單而有效的統(tǒng)一的API路由管理方式。
Spring Cloud Gateway作為Spring Cloud生態(tài)系統(tǒng)中的網(wǎng)關,目標是替代Netflix ZUUL,具有更好的性能、更強的擴展性、以及更豐富的功能特性,其不僅提供統(tǒng)一的路由方式,并且基于Filter鏈的方式提供了網(wǎng)關基本的功能,例如:安全,監(jiān)控/埋點,限流等。
3.Spring Cloud Gateway的特性
- 基于Spring Framework 5, Project Reactor和Spring Boot 2.0
- 動態(tài)路由:能夠匹配任何請求屬性
- 可以對路由指定 Predicate 和 Filter
- 集成Hystrix斷路器
- 集成Spring Cloud DiscoveryClient 服務發(fā)現(xiàn)功能
- 易于編寫的Predicate和Filter
- 請求限流
- 支持路徑重寫
4.Spring Cloud Gateway的三大核心概念
路由(Route): 路由是網(wǎng)關最基礎的部分,路由信息由一個ID,一個目標URI,一組斷言和過濾器組成。路由斷言Predicate用于匹配請求,過濾器Filter用于修改請求和響應。如果斷言為true,則說明請求URI和配置匹配,則執(zhí)行路由。
spring:
cloud:
gateway:
# 定義多個路由
routes:
# 一個路由route的id
- id: path_route
# 該路由轉發(fā)的目標URI
uri: https://example.org
# 路由條件集合
predicates:
- Path=/test/**
# 過濾器集合
filters:
- AddRequestHeader=X-Request-Id, 1024
- AddRequestParameter=color, red
斷言(Predicate): 參考Java8中的斷言Predicate,用于實現(xiàn)請求匹配邏輯,例如匹配路徑、請求頭、請求參數(shù)等。請求與斷言匹配則執(zhí)行該路由。
過濾器(Filter): 指的是Spring框架中GatewayFilter
的實例,使用過濾器,可以在請求被路由前后對請求進行修改。
5.Gateway工作流程
客戶端向Spring Cloud Gateway
發(fā)出請求,然后在Gateway Handler Mapping
中找到與請求相匹配的路由,將其發(fā)送到Gateway Web Handler
。Handler再通過指定的過濾器鏈來對請求進行過濾處理,最后發(fā)送到我們實際的服務執(zhí)行業(yè)務邏輯,然后返回。
過濾器鏈被虛線分隔,是因為過濾器既可以在轉發(fā)請求前攔截請求,也可以在請求處理之后對響應進行攔截處理。
推薦一個開源免費的 Spring Boot 實戰(zhàn)項目:
https://github.com/javastacks/spring-boot-best-practice
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,沒有固定規(guī)則但要求唯一,建議配合服務名
- 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.動態(tài)路由
網(wǎng)關接收外部請求,按照一定的規(guī)則,將請求轉發(fā)給其他服務或者應用。如果站在服務調用的角度,網(wǎng)關就扮演著服務消費者的角色,此時,如果再來看看服務調用的目標URI配置,就會很自然的發(fā)現(xiàn)一個問題,服務提供者調用的地址是寫死的,即網(wǎng)關沒有動態(tài)的發(fā)現(xiàn)服務,這就涉及到了服務的自動發(fā)現(xiàn)問題,以及發(fā)現(xiàn)服務后,所涉及到的服務調用的負載均衡的問題。
可以通過Nacos或者Eureka注冊中心動態(tài)發(fā)現(xiàn)服務,通過Ribbon進行服務調用的負載均衡。同樣,Gateway也可以整合Nacos或者Eureka,Ribbon從而實現(xiàn)動態(tài)路由的功能。
想要使用動態(tài)路由的功能,首先要整合注冊中心,這里以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,沒有固定規(guī)則但要求唯一,建議配合服務名
- id: config_route
#匹配后提供服務的路由地址, 這里lb之后,跟的是要調用的服務名稱
uri: lb://nacos-provider-8002
# 斷言,路徑相匹配的條件
predicates:
- Path=/routeconfig/rest/**
此時,當id為config_route
的路由規(guī)則匹配某個請求后,在調用該請求對應的服務時,就會從nacos注冊中心自動發(fā)現(xiàn)服務,并在服務調用的時候實現(xiàn)負載均衡。
8.Predicate
在Gateway中,有一些的內置Predicate Factory
,有了這些Pridicate Factory
,在運行時,Gateway會 自動根據(jù)需要創(chuàng)建其對應的Pridicate對象測試路由條件。
Path 路由斷言 Factory: 根據(jù)請求路徑匹配的路由條件工廠
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
# 如果可以匹配的PathPattern有多個,則每個路徑模式以,分開
- Path=/red/{segment},/blue/{segment}
After 路由斷言 Factory: 在指定日期時間之后發(fā)生的請求都將被匹配
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有兩個參數(shù),cookie名稱和正則表達式。請求包含此cookie名稱且正則表達式為真的將會被匹配。
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
Header 路由斷言 Factory: Header 路由斷言 Factory有兩個參數(shù),header名稱和正則表達式。請求包含此header名稱且正則表達式為真的將會被匹配。
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
Host 路由斷言 Factory: Host 路由斷言 Factory包括一個參數(shù):host name列表。使用Ant路徑匹配規(guī)則, . 作為分隔符。
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
Method 路由斷言 Factory: Method 路由斷言 Factory只包含一個參數(shù):需要匹配的HTTP請求方式
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET
自定義Predicate
可以自定義Predicate來實現(xiàn)復雜的路由匹配規(guī)則:
// 實現(xiàn)自定義 Predicate 工廠
// 通過HostRoutePredicateFactory創(chuàng)建Predicate進行路由判斷
@Component
public class MyHostRoutePredicateFactory extends AbstractRoutePredicateFactory<MyHostRoutePredicateFactory.Config> {
public MyHostRoutePredicateFactory() {
// Config 類作為 Predicate 的配置參數(shù)類
super(Config.class);
}
public static class Config {
// 路由匹配規(guī)則
private String hostName;
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
}
// 生成一個 Predicate 實例
@Override
public Predicate<ServerWebExchange> apply(Config config) {
// 實現(xiàn)匹配邏輯
return exchange -> {
// 根據(jù)config實現(xiàn)匹配判斷
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
可以通過實現(xiàn)GatewayFilter和Ordered接口自定義Filter來實現(xiàn)請求處理邏輯:
@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
:在請求頭中添加參數(shù) -
PrefixPath GatewayFilter
:請求路徑前綴 -
Hystrix GatewayFilter
: 斷路器 -
RateLimit GatewayFilter
: 限流 -
Retry GatewayFilter
: 重試
來源:blog.csdn.net/Cristiano272/article/details/131814765
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協(xié)程要來了。。。
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優(yōu)雅的方式??!
5.《Java開發(fā)手冊(嵩山版)》最新發(fā)布,速速下載!文章來源:http://www.zghlxwxcb.cn/news/detail-705826.html
覺得不錯,別忘了隨手點贊+轉發(fā)哦!文章來源地址http://www.zghlxwxcb.cn/news/detail-705826.html
到了這里,關于Spring Cloud Gateway:新一代微服務 API 網(wǎng)關,用起來真優(yōu)雅!的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!