在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    SpringCloud系列-10Spring Cloud Gateway網(wǎng)關(guān)

    SpringCloud系列-10Spring Cloud Gateway網(wǎng)關(guān)

    學習目標

  • Gateway是什么?它有什么作用?
  • Gateway中的斷言使用
  • Gateway中的過濾器使用
  • Gateway中的路由使用
  • 第1章 網(wǎng)關(guān)

    1.1 網(wǎng)關(guān)的概念

    簡單來說,網(wǎng)關(guān)就是一個網(wǎng)絡(luò)連接到另外一個網(wǎng)絡(luò)的“關(guān)口”。如下圖所示,當我們所在的本地網(wǎng)絡(luò)(局域網(wǎng))要訪問外部網(wǎng)絡(luò)的數(shù)據(jù)時,需要通過路由器進行轉(zhuǎn)發(fā),而這里的路由器就充當了網(wǎng)關(guān)的角色。

    1.2 網(wǎng)關(guān)的作用

    網(wǎng)關(guān)的作用,是可以實現(xiàn)不同網(wǎng)絡(luò)之間的互聯(lián),同時,還可以使得在不同的通信協(xié)議、數(shù)據(jù)格式等系統(tǒng)之間實現(xiàn)轉(zhuǎn)發(fā)。

    我們今天要講解的Gateway,它也是網(wǎng)關(guān)的一種,我們稱為應(yīng)用網(wǎng)關(guān),也稱為API網(wǎng)關(guān)。為什么需要API網(wǎng)關(guān)呢? 還得從架構(gòu)演變過程來說明:

    前面我們說過,在微服務(wù)架構(gòu)中,每個微服務(wù)都是一個獨立運行的組件,這些組件通過Rest API風格的接口給到H5、Android、IOS等客戶端程序調(diào)用。(移動互聯(lián)時代,為了盡快迭代)。而在一個UI界面中,通常會展示很多數(shù)據(jù),這些數(shù)據(jù)可能來自不同的微服務(wù),比如在一個電商系統(tǒng)中,執(zhí)行一個下單請求,必然需要

  • 從營銷服務(wù)中查詢促銷信息
  • 從會員服務(wù)中查詢會員等級和會員積分等
  • 從商品服務(wù)查詢商品詳情
  • 調(diào)用訂單服務(wù)進行下單。
  • 1.3 出現(xiàn)的背景

    那么早期的微服務(wù)架構(gòu),面對這樣的情況的處理方式,出現(xiàn)了如下圖所示的調(diào)用方式。

    在這種調(diào)用方式中,不難發(fā)現(xiàn)問題會比較多:

  • 客戶端和內(nèi)部微服務(wù)的耦合度較高,任何一邊發(fā)生變化,都會對另外一邊造成影響
  • 客戶端需要維護內(nèi)部微服務(wù)的地址等信息,如果微服務(wù)地址發(fā)生變化也會影響客戶端的通信
  • 客戶端需要調(diào)用多次接口請求,造成服務(wù)端請求過多
  • 這種方式存在較多的問題,所以一般我們會在客戶端與微服務(wù)之間引入BFF層(即 Backend For Frontend(服務(wù)于前端的后端)),也就是服務(wù)器設(shè)計API時會考慮前端的使用,并在服務(wù)端直接進行業(yè)務(wù)邏輯的處理,又稱為用戶體驗適配器。

    如下圖所示,BFF層為客戶端提供了統(tǒng)一的聚合服務(wù),我們可以在BFF層為不同的端或者不同的業(yè)務(wù)提供更加友好和統(tǒng)一的客戶端。

    引入BFF層的好處是

  • 客戶端和內(nèi)部微服務(wù)之間不存在之間耦合,使得兩端的變化可以獨立
  • 當APP端有新的需求時,可以通過BFF層進行評比,減少后端團隊的溝通成本,如果后端微服務(wù)設(shè)計得足夠好的話,很多的需求在BFF層就可以搞定。
  • 但是這種方式仍然存在問題,客戶端發(fā)起請求進入到BFF層時,需要考慮到安全問題,需要做鑒權(quán)、限流等,而這些功能需要在每一個BFF模塊中都需要編寫,增加了很多的重復(fù)代碼,而且維護起來非常不靈活導致開發(fā)效率下降。

    所以,引入了API網(wǎng)關(guān),整體結(jié)構(gòu)如下圖所示

    網(wǎng)關(guān)是微服務(wù)架構(gòu)不可或缺的一部分,作為微服務(wù)架構(gòu)的唯一入口,將所有請求轉(zhuǎn)發(fā)到后端對應(yīng)的微服務(wù)上去,同時又可以將各個微服務(wù)中的通用功能集中到網(wǎng)關(guān)去做,而不是在每個微服務(wù)都實現(xiàn)一遍,

  • 身份驗證和授權(quán)
  • 限流
  • 版本控制
  • 緩存
  • 統(tǒng)一日志
  • 同時,增加網(wǎng)關(guān)后,把各個BFF模塊的橫切功能剝離到網(wǎng)關(guān)中,BFF模塊開發(fā)人員只需要關(guān)注在業(yè)務(wù)邏輯的交付上。

    常見的開源網(wǎng)關(guān)

  • OpenResty(Nginx+lua)
  • Zuul,是spring cloud生態(tài)下提供的一個網(wǎng)關(guān)服務(wù),性能相對來說不是很高
  • Spring Cloud Gateway,是Spring團隊開發(fā)的高性能網(wǎng)關(guān)
  • 1.4 Gateway簡介

    Spring Cloud Gateway 是 Spring 官方團隊研發(fā)的 API 網(wǎng)關(guān)技術(shù),它的目的是取代 Zuul 為微服務(wù)提供一種簡單高效的 API 網(wǎng)關(guān)。一般來說,Spring 團隊不會重復(fù)造輪子,為什么又研發(fā)出一個 Spring Cloud Gateway 呢?有幾方面原因。

    • Zuul1.x 采用的是傳統(tǒng)的 thread per connection 方式來處理請求,也就是針對每一個請求,會為這個請求專門分配一個線程來進行處理,直到這個請求完成之后才會釋放線程,一旦后臺服務(wù)器響應(yīng)較慢,就會使得該線程被阻塞,所以它的性能不是很好。
    • Zuul 本身存在的一些性能問題不適合于高并發(fā)的場景,雖然后來 Netflix 決定開發(fā)高性能版 Zuul 2.x,但是 Zuul 2.x 的發(fā)布時間一直不確定。雖然 Zuul 2.x 后來已經(jīng)發(fā)布并且開源了,但是 Spring Cloud 并沒有打算集成進來。Spring Cloud Gateway 是依賴于 Spring Boot 2.0、Spring WebFlux 和 Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān),它不僅提供了統(tǒng)一的路由請求的方式,還基于過濾鏈的方式提供了網(wǎng)關(guān)最基本的功能。

    1.5 Gateway基本概念

    Spring Cloud Gateway的基本工作原理如下圖所示。

    客戶端向Spring Cloud Gateway發(fā)出請求。然后在Gateway Handler Mapping中找到與請求相匹配的路由,將其發(fā)送到Gateway Web Handler。Handler 再通過指定的過濾器鏈來將請求發(fā)送到我們實際的服務(wù)執(zhí)行業(yè)務(wù)邏輯,然后返回。

    過濾器之間用虛線分開是因為過濾器可能會在發(fā)送代理請求之前(“pre”)或之后(“post”)執(zhí)行業(yè)務(wù)邏輯。

    • Filter在“pre”類型的過濾器可以做參數(shù)校驗、權(quán)限校驗、流量監(jiān)控、日志輸出、協(xié)議轉(zhuǎn)換等,
    • 在“post”類型的過濾器中可以做響應(yīng)內(nèi)容、響應(yīng)頭的修改,日志的輸出,流量監(jiān)控等有著非常重要的作用。

    在Spring Cloud Gateway中有三個重要的對象,分別是:

    • Route路由,它是網(wǎng)關(guān)的基礎(chǔ)元素,包含ID、目標URI、斷言、過濾器組成,當前請求到達網(wǎng)關(guān)時,會通過Gateway Handler Mapping,基于斷言進行路由匹配,當斷言為true時,匹配到路由進行轉(zhuǎn)發(fā)
    • Predicate斷言,學過java8的同學應(yīng)該知道這個函數(shù),它可以允許開發(fā)人員去匹配HTTP請求中的元素,一旦匹配為true,則表示匹配到合適的路由進行轉(zhuǎn)發(fā)
    • Filter過濾器,可以在請求發(fā)出的前后進行一些業(yè)務(wù)上的處理,比如授權(quán)、埋點、限流等。

    具體的工作原理如下圖所示:

    它的整體工作原理如下。

    其中,predicate就是我們的匹配條件;而filter,就可以理解為一個無所不能的攔截器。有了這兩個元素,再加上目標uri,就可以實現(xiàn)一個具體的路由了。

    客戶端向 Spring Cloud Gateway 發(fā)出請求,如果請求與網(wǎng)關(guān)程序定義的路由匹配,則該請求就會被發(fā)送到網(wǎng)關(guān) Web 處理程序,此時處理程序運行特定的請求過濾器鏈。

    過濾器之間用虛線分開的原因是過濾器可能會在發(fā)送代理請求的前后執(zhí)行邏輯。所有 pre 過濾器邏輯先執(zhí)行,然后執(zhí)行代理請求;代理請求完成后,執(zhí)行 post 過濾器邏輯。

    第2章 Predicate應(yīng)用

    下面我們通過一些案例演示來初步了解Spring Cloug Gateway.

    1.在上文的基礎(chǔ)之上,整個項目拷貝過來,并改名為gateway-**

    2.在上面的框架基礎(chǔ)之上,修改user項目中的HelloController和UserController

    @RestControllerpublic class HelloController { @Autowired OrderServiceClient orderServiceClient; @Value(“${server.port}”) private int port; @GetMapping(“/hello/{name}”) public String get(@PathVariable(“name”) String name){ String result = “”; //同步 result = new HelloCommand(name,orderServiceClient).execute(); return “當前user端口為:”+port+”,結(jié)果為:”+result; }}@RestControllerpublic class UserController { @Autowired OrderServiceClient orderServiceClient; @Value(“${server.port}”) private int port; @HystrixCommand(commandProperties = { @HystrixProperty(name=”circuitBreaker.requestVolumeThreshold”,value = “10”), @HystrixProperty(name=”circuitBreaker.sleepWindowInMilliseconds”,value=”5000″), @HystrixProperty(name=”circuitBreaker.errorThresholdPercentage”,value=”50″), },fallbackMethod = “fallback”) @GetMapping(“/get/{num}”) public String get(@PathVariable(“num”) int num){ if(num%2==0){ return “當前user端口為:”+port+”,結(jié)果為:正常訪問”; } return “當前user端口為:”+port+”,結(jié)果為:”+orderServiceClient.orderLists(num); } public String fallback(int num){ return “觸發(fā)降級”; }}

    并分別開啟兩個user項目,端口為8080和8081;開啟兩個order項目,端口分別為8088和8099

    3.創(chuàng)建新的springboot項目gateway-common

    4.配置pom

    4.0.0 eclipse2019-demo com.example 1.0-SNAPSHOT com.example gateway-common 0.0.1-SNAPSHOT gateway-common Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-test test org.springframework.cloud spring-cloud-starter-gateway org.springframework.cloud spring-cloud-starter-netflix-eureka-client

    5.配置yml,如果用的是nacos,一般這些配置可以寫在nacos里面

    server: port: 9527 spring: application: name: gateway cloud: gateway: routes: # 路由的ID,沒有固定規(guī)則但要求唯一,建議配合服務(wù)名 – id: getUser # 匹配后提供服務(wù)的路由地址 uri: http://localhost:8080 # 斷言,路徑相匹配的進行路由 predicates: – Path=/get/** – id: sayHello uri: http://localhost:8081 predicates: – Path=/hello/** – id: heihei uri: https://www.baidu.com/ predicates: – Path=/heihei/** filters: – StripPrefix=1 #去掉地址中的第一部分 – StripPrefix=2 #去掉地址中的第二部分eureka: instance: hostname: gateway-9527 client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://127.0.0.1:8761/eureka

    6.啟動類

    @SpringBootApplication@EnableDiscoveryClientpublic class GatewayCommonApplication { public static void main(String[] args) { SpringApplication.run(GatewayCommonApplication.class, args); } }

    7.測試

    2.1 Predicate規(guī)則

    上述案例中,我們使用了Gateway中的 Path匹配規(guī)則,也就是根據(jù)請求的uri地址,使用前綴匹配規(guī)則完成請求地址的匹配。

    Gateway內(nèi)置了是多種Predicate匹配規(guī)則,具體如下圖所示

    2.1.1 Query斷言

    Query 路由斷言工廠接收兩個參數(shù),一個必需的參數(shù)和一個可選的正則表達式。

    spring: cloud: gateway: routes: – id: query_route uri: https://www.baidu.com/ predicates: – Query=name, eclipse2019.*shuai

    如果請求包含一個name的參數(shù),值是eclipse2019開頭,shuaiqi結(jié)尾,則此路由將匹配。第二個參數(shù)是正則表達式。

    測試鏈接:http://localhost:9527/?name=feichangshuaiqieclipse2019

    2.1.2 Method斷言

    Method 路由斷言工廠接收一個參數(shù),即要匹配的 HTTP 方法。

    spring: cloud: gateway: routes: – id: method_route uri: https://www.douyu.com/ predicates: – Method=GET

    2.1.3 Header斷言

    Header 路由斷言工廠接收兩個參數(shù),分別是請求頭名稱和正則表達式。

    spring: cloud: gateway: routes: – id: header_route uri: https://www.douyin.com/ predicates: – Header=X-Request-Id, d+

    如果請求中帶有請求頭名為 X-Request-Id,其值與 d+ 正則表達式匹配(值為一個或多個數(shù)字),則此路由匹配。

    2.1.4 Cookie斷言

    spring: cloud: gateway: routes: – id: cookie_route uri: https://www.huya.com/ predicates: – Cookie=name,eclipse2019

    通過postman,訪問http://localhost:9527 ; 并且在請求中攜帶cookie name=eclipse2019。 即可匹配到路由進行轉(zhuǎn)發(fā)。

    2.2 自定義Predicate

    除了使用到官方提供的斷言工廠之外,如果我們有個性化的需求,也是可以實現(xiàn)自定義斷言工廠的。自定義路由斷言工廠需要繼承 AbstractRoutePredicateFactory 類,重寫 apply 方法的邏輯。在 apply 方法中可以通過 exchange.getRequest() 拿到 ServerHttpRequest 對象,從而可以獲取到請求的參數(shù)、請求方式、請求頭等信息。

    apply 方法的參數(shù)是自定義的配置類,在使用的時候配置參數(shù),在 apply 方法中直接獲取使用。

    命名需要以 RoutePredicateFactory 結(jié)尾,比如 AuthRoutePredicateFactory,那么在使用的時候Auth 就是這個路由斷言工廠的名稱。代碼如下所示。

    1.自定義AuthRoutePredicateFactory

    @Componentpublic class AuthRoutePredicateFactory extends AbstractRoutePredicateFactory{ Logger logger= LoggerFactory.getLogger(AuthRoutePredicateFactory.class); public static final String NAME_KEY = “name”; public AuthRoutePredicateFactory() { super(Config.class); } @Override public List shortcutFieldOrder() { return Arrays.asList(NAME_KEY); } @Override public Predicate apply(Config config) { logger.info(“AuthRoutePredicateFactory Start”); //只要請求的header中包含yml配置的Authorization,就允許匹配路由 return exchange -> { HttpHeaders headers=exchange.getRequest().getHeaders(); List header=headers.get(config.getName()); return header.size()>0; }; } public static class Config{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }}

    2.在配置文件中添加如下配置信息

    – id: define_route uri: https://www.baidu.com predicates: – Path=/define/** – Auth=Authorization filters: – StripPrefix=1

    3.訪問測試

  • postman中訪問url:http://localhost:9527/define/1測試: 在header中添加Authorization 以及不添加 Authorization的效果。
  • 第3章 Filter應(yīng)用

    filter是網(wǎng)關(guān)中的核心,它起到了請求過濾的作用。在gateway中,會對請求做pre和post的過濾,pre表示請求進來之前,post表示請求處理完成之后返回給客戶端之前。

    • pred類型的過濾器可以做授權(quán)認證、流量監(jiān)控、協(xié)議轉(zhuǎn)化等工作
    • post過濾器可以做響應(yīng)內(nèi)容的修改、日志的輸出等。

    下圖表示的是請求和響應(yīng),經(jīng)過filter的處理流程。

    3.1 Filter分類

    在Spring Cloud Gateway中,F(xiàn)ilter按照作用范圍可以分為兩類

    全局過濾器,針對所有的請求都會被攔截

    局部過濾器,只針對某一個指定的route有效

    我們先來了解一下局部過濾器,在前面講Predicate的時候,其實已經(jīng)涉及到了Filter的使用。

    在Spring Cloud Gateway中,內(nèi)置了非常多的過濾器,如下圖所示

    3.2 常用Filter

    3.2.1 AddRequestParameter

    針對所有匹配的請求,添加一個查詢參數(shù)。

    下面這段配置,會針對所有請求增加一個tn=baiduimage&word=%E7%BE%8E%E5%A5%B3的參數(shù)

    spring: cloud: gateway: routes: – id: add_request_parameter_route uri: https://image.baidu.com/ predicates: – Path=/search/index/** filters: – AddRequestParameter=tn,baiduimage – AddRequestParameter=word,%E7%BE%8E%E5%A5%B3

    3.2.2 RequestRateLimiter

    該過濾器會對訪問到當前網(wǎng)關(guān)的所有請求執(zhí)行限流過濾,如果被限流,默認情況下會響應(yīng)HTTP 429-Too Many Requests。RequestRateLimiterGatewayFilterFactory 默認提供了 RedisRateLimiter 的限流實現(xiàn),它采用令牌桶算法來實現(xiàn)限流功能

    spring: cloud: gateway: routes: – id: request_ratelimiter_route uri: https://www.taobao.com/ predicates: – Path=/tb/** filters: – StripPrefix=1 – name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 2 redis-rate-limiter.burstCapacity: 5 key-resolver: “#{@userkeyResolver}” #這個必須要配置,否則返回403

    redis-rate-limiter 過濾器有兩個配置屬性,如果大家了解令牌桶,就很容易知道它們的含義。

    • replenishRate:令牌桶中令牌的填充速度,代表允許每秒執(zhí)行的請求數(shù)。
    • burstCapacity:令牌桶的容量,也就是令牌桶最多能夠容納的令牌數(shù)。表示每秒用戶最大能夠執(zhí)行的請求數(shù)量。
    • key-resolver:關(guān)鍵字標識的限流

    使用redis限流的話還要做一些事:

    1.pom中引包

    org.springframework.boot spring-boot-starter-data-redis-reactive

    2.設(shè)置redis的地址

    spring: redis: database: 1 password: eclipse2019 host: localhost

    3.在啟動類或者配置類中加如下代碼

    @BeanKeyResolver userkeyResolver(){ //根據(jù)請求的ip進行限流 return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());}

    3.2.3 Retry

    Retry GatewayFilter Factory 為請求重試過濾器,當后端服務(wù)不可用時,網(wǎng)關(guān)會根據(jù)配置參數(shù)來發(fā)起重試請求

    spring: cloud: gateway: routes: – id: retry_route uri: http://www.example.com predicates: – Path=/example/** filters: – name: Retry args: retries: 3 status: 503 – StripPrefix=1

    RetryGatewayFilter 提供 4 個參數(shù)來控制重試請求,參數(shù)說明如下。

    • retries:請求重試次數(shù),默認值是 3。
    • status:HTTP 請求返回的狀態(tài)碼,針對指定狀態(tài)碼進行重試,比如,在上述配置中,當服務(wù)端返回的狀態(tài)碼是 503 時,才會發(fā)起重試,此處可以配置多個狀態(tài)碼。
    • methods:指定 HTTP 請求中哪些方法類型需要進行重試,默認是 GET。
    • series:配置錯誤碼段,表示符合某段狀態(tài)碼才發(fā)起重試,默認值是 SERVER_ERROR(5),表示 5xx 段的狀態(tài)碼都會發(fā)起重試。如果 series 配置了錯誤碼段,但是 status 沒有配置,則仍然會匹配 series 進行重試。

    3.2.4 全局過濾器

    全局過濾器和GatewayFilter的作用是相同的,只是GlobalFilter針對所有的路由配置生效。Spring Cloud Gateway默認內(nèi)置了一些全局過濾器

    • GatewayMetricsFilter,提供監(jiān)控指標。
    • ReactiveLoadBalancerClientFilter,整合 Ribbon 針對下游服務(wù)實現(xiàn)負載均衡。
    • ForwardRoutingFilter,用于本地 forward,請求不轉(zhuǎn)發(fā)到下游服務(wù)器。
    • NettyRoutingFilter,使用 Netty 的 HttpClient 轉(zhuǎn)發(fā) HTTP、HTTPS 請求
    • ….

    全局過濾鏈的執(zhí)行順序是,當 Gateway 接收到請求時,F(xiàn)iltering Web Handler 處理器會將所有的 GlobalFilter 實例及所有路由上所配置的 GatewayFilter 實例添加到一條過濾器鏈中。該過濾器鏈里的所有過濾器都會按照@Order 注解所指定的數(shù)字大小進行排序。

    3.2.5 自定義過濾器

    雖然Spring Cloud Gateway提供了非常多的過濾器,但是在實際應(yīng)用中,我們必然會涉及到和業(yè)務(wù)有關(guān)的過濾器,比如日志記錄、鑒權(quán)、黑白名單等。Spring Cloud Gateway 提供了過濾器的擴展功能,開發(fā)者可以根據(jù)實際業(yè)務(wù)需求來自定義過濾器,這樣我們就可以在網(wǎng)關(guān)層實現(xiàn)時鑒權(quán)、日志管理、協(xié)議轉(zhuǎn)化等功能。同樣,自定義過濾器也支持 GlobalFilter 和 GatewayFilter 兩種。

    3.2.5.1 自定義GatewayFilter

    首先創(chuàng)建一個自定義過濾器類MyDefineGatewayFilterFactory,繼承AbstractGatewayFilterFactory。

    @Componentpublic class MyDefineGatewayFilterFactory extends AbstractGatewayFilterFactory{ Logger logger= LoggerFactory.getLogger(MyDefineGatewayFilterFactory.class); public static final String NAME_KEY = “name”; public MyDefineGatewayFilterFactory() { super(MyConfig.class); } @Override public List shortcutFieldOrder() { return Arrays.asList(NAME_KEY); } @Override public GatewayFilter apply(MyConfig config) { return ((exchange, chain) -> { logger.info(“[Pre] Filter Request,name:”+config.getName()); //then接收一個變量,然后then前面處理的那個就結(jié)束了,后面開始處理then接收的這個變量 return chain.filter(exchange).then(Mono.fromRunnable(()->{ logger.info(“[Post] Response Filter”); })); }); } public static class MyConfig{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }}

    在上述代碼中,有幾點需要注意:

    • 類名必須要統(tǒng)一以GatewayFilterFactory結(jié)尾,因為默認情況下過濾器的 name 會采用該自定義類的前綴。這里的 name=MyDefine。
    • 在apply方法中,同時包含Pre和Post過濾。在then方法中是請求執(zhí)行結(jié)束之后的后置處理。
    • MyConfig 是一個配置類,該類中只有一個屬性 name。這個屬性可以在 yml 文件中使用。
    • 該類需要裝載到 Spring IoC 容器,此處使用@Component注解實現(xiàn)。

    接下來,修改application.yml,增加自定義過濾器配置

    spring: cloud: gateway: routes: – id: define_route uri: http://localhost:8080 predicates: – Path=/define/** filters: – MyDefine=My_Eclipse2019

    此時訪問到這個過濾器,就會輸出如下日志,說明進入到了網(wǎng)關(guān)攔截器。

    2020-06-02 22:08:21.838 INFO 164 — [ioEventLoop-5-2] c.e.s.MyDefineGatewayFilterFactory : [Pre] Filter Request,name:My_Eclipse20192020-06-02 22:08:21.875 INFO 164 — [ctor-http-nio-5] c.e.s.MyDefineGatewayFilterFactory : [Post] Response Filter

    3.2.5.2 自定義GlobalFilter

    GlobalFilter 的實現(xiàn)比較簡單,它不需要額外的配置,只需要實現(xiàn) GlobalFilter 接口,自動會過濾所有的 Route

    @Servicepublic class MyDefineFilter implements GlobalFilter,Ordered{ Logger log= LoggerFactory.getLogger(MyDefineFilter.class); @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info(“[pre]-Enter MyDefineFilter”); return chain.filter(exchange).then(Mono.fromRunnable(()->{ log.info(“[post]-Return Result”); })); } @Override public int getOrder() { return 0; }}

    getOrder 表示該過濾器的執(zhí)行順序,值越小,執(zhí)行優(yōu)先級越高。需要注意的是,我們通過 AbstractGatewayFilterFactory 實現(xiàn)的局部過濾器沒有指定 order,它的默認值是 0,如果想要設(shè)置多個過濾器的執(zhí)行順序,可以重寫 getOrder 方法。

    第4章 路由

    4.1 基于集群負載均衡路由

    當被路由的目標服務(wù)是一個集群節(jié)點時,就會涉及到集群路由,Spring Cloud Gateway提供了一個LoadBalancerClientFilter全局過濾器,來實現(xiàn)負載均衡的解析。

    1.增加jar包依賴

    org.springframework.cloud spring-cloud-starter-netflix-eureka-client

    2.user項目也要注冊到Eureka上面去

    3.修改application.yml配置

    spring: application: name: gateway redis:database: 1 password: eclipse2019 host: localhost cloud: gateway: routes: – id: getUser uri: lb://user # 修改這里 predicates: – Path=/get/** discovery: # 修改這里 locator: enabled: true lower-case-service-id: true server: port: 9527eureka: # 修改這 instance: hostname: gateway-9527 client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://127.0.0.1:8761/eureka

    增加部分的配置說明如下

    • lower-case-service-id:是否使用 service-id 的小寫,默認是大寫。
    • spring.cloud.gateway.discovery.locator.enabled:開啟從注冊中心動態(tài)創(chuàng)建路由的功能。
    • uri 中配置的lb://表示從注冊中心獲取服務(wù),后面的user表示目標服務(wù)在注冊中心上的服務(wù)名

    重啟gateway-common項目,訪問:http://localhost/get/3接口。

    4.2 動態(tài)路由的實現(xiàn)

    在實際應(yīng)用中, 我們還會存在一種:動態(tài)配置路由的需求。也就是在運行過程中,動態(tài)增加或者修改網(wǎng)關(guān)路由配置,這個需求在Spring Cloud Gateway中如何實現(xiàn)呢?

    在Spring Cloud Gateway中,提供了GatewayControllerEndpoint這個類來實現(xiàn)路由的動態(tài)修改,可以通過actuator打開這些endpoint信息

    1.添加Pom依賴

    org.springframework.boot spring-boot-starter-actuator

    2.修改application.yml,開發(fā)所有endpoint

    management: endpoints: web: exposure: include: *

    4.2.1 檢索網(wǎng)關(guān)中定義的路由

    通過這個地址:http://localhost:9527/actuator/gateway/routes可以獲得當前網(wǎng)關(guān)中所有定義的路由

    [ { predicate: “Paths: [/get/**], match trailing slash: true”, route_id: “getUser”, filters: [ ], uri: “lb://user”, order: 0, }]

    其中:

    • route_id 表示路由編號
    • route_object.predicate 表示路由的條件匹配謂詞
    • route_object.filters 表示網(wǎng)關(guān)過濾器
    • order 路由順序

    4.2.2 查找特定的路由信息。

    http://localhost:9527/actuator/gateway/routes/{route_id}

    4.2.3 刷新路由緩存

    {POST請求}http://localhost:9527/actuator/gateway/refresh

    4.2.4 增減、修改路由

    /gateway/routes/{id} @PostMapping 新增一個路由信息

    /gateway/routes/{id} @DeleteMapping 刪除一個路由信息

    1.案例演示(添加路由)

    • 通過POST請求添加一個路由信息,http://localhost:9527/actuator/gateway/routes/baidu_route

    { “uri”: “https://www.baidu.com”, “predicates”: [{ “args”: { “pattern”: “/baidu/**” }, “name”: “Path” }], “filters”: [{ “args”: { “_genkey_0”: 1 }, “name”: “StripPrefix” }]}

    • 執(zhí)行:{POST請求}http://localhost:9527/actuator/gateway/refresh刷新路由。
    • 通過訪問:http://localhost:9527/actuator/gateway/routes 查看當前路由列表,可以發(fā)現(xiàn)多了一個段這樣的內(nèi)容。

    { predicate: “Paths: [/baidu/**], match trailing slash: true”, route_id: “baidu_route”, filters: [ “[[StripPrefix parts = 1], order = 1]” ], uri: “https://www.baidu.com:443”, order: 0,}

    • 此時我們訪問: http://localhost:9527/baidu ,就會路由到百度搜索引擎這個網(wǎng)址。

    2.案例演示(刪除路由)

    • 通過/gateway/routes/{id} @DeleteMapping 刪除一個路由信息
    • 通過postman調(diào)用 /gateway/routes/baidu_route (delete請求), 就可以刪除路由,刪除路由之后再次訪問路由列表頁面,此時可以發(fā)現(xiàn)路由信息是被刪除的。

    4.2.5 小結(jié)

    基于Spring Cloud Gateway默認方法實現(xiàn)的動態(tài)路由就講解完了,但是通過這種形式是去更新的動態(tài)路由信息,是基于內(nèi)存來實現(xiàn)的。一旦服務(wù)重啟,新增的路由配置信息就會全部清空,所以這個時候我們可以參考GatewayControllerEndpoint這個類,來自己實現(xiàn)一套動態(tài)路由的方法。并且將路由信息持久化。

    在實際開發(fā)中也可以通過Nacos作為配置中心直接在Nacos上面增加。

    下文預(yù)告

  • Gateway核心源碼分析
  • 鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
    上一篇 2022年7月11日 09:33
    下一篇 2022年7月11日 09:33

    相關(guān)推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時間:周一至周五,10:30-18:30,節(jié)假日休息