免费爱碰视频在线观看,九九精品国产屋,欧美亚洲尤物久久精品,1024在线观看视频亚洲

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

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

      學(xué)習(xí)目標(biāo)

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

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

      簡單來說,網(wǎng)關(guān)就是一個網(wǎng)絡(luò)連接到另外一個網(wǎng)絡(luò)的“關(guān)口”。如下圖所示,當(dāng)我們所在的本地網(wǎng)絡(luò)(局域網(wǎng))要訪問外部網(wǎng)絡(luò)的數(shù)據(jù)時,需要通過路由器進行轉(zhuǎn)發(fā),而這里的路由器就充當(dāng)了網(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風(fēng)格的接口給到H5、Android、IOS等客戶端程序調(diào)用。(移動互聯(lián)時代,為了盡快迭代)。而在一個UI界面中,通常會展示很多數(shù)據(jù),這些數(shù)據(jù)可能來自不同的微服務(wù),比如在一個電商系統(tǒng)中,執(zhí)行一個下單請求,必然需要

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

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

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

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

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

      引入BFF層的好處是

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

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

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

    24. OpenResty(Nginx+lua)
    25. Zuul,是spring cloud生態(tài)下提供的一個網(wǎng)關(guān)服務(wù),性能相對來說不是很高
    26. Spring Cloud Gateway,是Spring團隊開發(fā)的高性能網(wǎng)關(guān)
    27. 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、目標(biāo)URI、斷言、過濾器組成,當(dāng)前請求到達(dá)網(wǎng)關(guān)時,會通過Gateway Handler Mapping,基于斷言進行路由匹配,當(dāng)斷言為true時,匹配到路由進行轉(zhuǎn)發(fā)
      • Predicate斷言,學(xué)過java8的同學(xué)應(yīng)該知道這個函數(shù),它可以允許開發(fā)人員去匹配HTTP請求中的元素,一旦匹配為true,則表示匹配到合適的路由進行轉(zhuǎn)發(fā)
      • Filter過濾器,可以在請求發(fā)出的前后進行一些業(yè)務(wù)上的處理,比如授權(quán)、埋點、限流等。

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

      它的整體工作原理如下。

      其中,predicate就是我們的匹配條件;而filter,就可以理解為一個無所不能的攔截器。有了這兩個元素,再加上目標(biāo)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 “當(dāng)前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 “當(dāng)前user端口為:”+port+”,結(jié)果為:正常訪問”; } return “當(dāng)前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ù)和一個可選的正則表達(dá)式。

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

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

      測試鏈接: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ù),分別是請求頭名稱和正則表達(dá)式。

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

      如果請求中帶有請求頭名為 X-Request-Id,其值與 d+ 正則表達(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.訪問測試

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

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

      • pred類型的過濾器可以做授權(quán)認(rè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

      該過濾器會對訪問到當(dāng)前網(wǎng)關(guān)的所有請求執(zhí)行限流過濾,如果被限流,默認(rèn)情況下會響應(yīng)HTTP 429-Too Many Requests。RequestRateLimiterGatewayFilterFactory 默認(rèn)提供了 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)鍵字標(biāo)識的限流

      使用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 為請求重試過濾器,當(dāng)后端服務(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ù),默認(rèn)值是 3。
      • status:HTTP 請求返回的狀態(tài)碼,針對指定狀態(tài)碼進行重試,比如,在上述配置中,當(dāng)服務(wù)端返回的狀態(tài)碼是 503 時,才會發(fā)起重試,此處可以配置多個狀態(tài)碼。
      • methods:指定 HTTP 請求中哪些方法類型需要進行重試,默認(rèn)是 GET。
      • series:配置錯誤碼段,表示符合某段狀態(tài)碼才發(fā)起重試,默認(rèn)值是 SERVER_ERROR(5),表示 5xx 段的狀態(tài)碼都會發(fā)起重試。如果 series 配置了錯誤碼段,但是 status 沒有配置,則仍然會匹配 series 進行重試。

      3.2.4 全局過濾器

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

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

      全局過濾鏈的執(zhí)行順序是,當(dāng) 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é)尾,因為默認(rèn)情況下過濾器的 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,它的默認(rèn)值是 0,如果想要設(shè)置多個過濾器的執(zhí)行順序,可以重寫 getOrder 方法。

      第4章 路由

      4.1 基于集群負(fù)載均衡路由

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

      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 的小寫,默認(rèn)是大寫。
      • spring.cloud.gateway.discovery.locator.enabled:開啟從注冊中心動態(tài)創(chuàng)建路由的功能。
      • uri 中配置的lb://表示從注冊中心獲取服務(wù),后面的user表示目標(biāo)服務(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可以獲得當(dāng)前網(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 查看當(dāng)前路由列表,可以發(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默認(rèn)方法實現(xiàn)的動態(tài)路由就講解完了,但是通過這種形式是去更新的動態(tài)路由信息,是基于內(nèi)存來實現(xiàn)的。一旦服務(wù)重啟,新增的路由配置信息就會全部清空,所以這個時候我們可以參考GatewayControllerEndpoint這個類,來自己實現(xiàn)一套動態(tài)路由的方法。并且將路由信息持久化。

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

      下文預(yù)告

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

      相關(guān)推薦

      聯(lián)系我們

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