成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我去,你竟然還不會(huì)用API網(wǎng)關(guān)!

原創(chuàng)
網(wǎng)絡(luò) 通信技術(shù) 開發(fā)工具
從應(yīng)用程序架構(gòu)的變遷過(guò)程可以發(fā)現(xiàn),隨著業(yè)務(wù)多變性、靈活性的不斷提高,應(yīng)用程序需要以更加靈活的組合來(lái)應(yīng)對(duì)。

【51CTO.com原創(chuàng)稿件】從應(yīng)用程序架構(gòu)的變遷過(guò)程可以發(fā)現(xiàn),隨著業(yè)務(wù)多變性、靈活性的不斷提高,應(yīng)用程序需要以更加靈活的組合來(lái)應(yīng)對(duì)。

[[326027]]

圖片來(lái)自 Pexels

同時(shí)為了應(yīng)對(duì)業(yè)務(wù)的細(xì)分以及高并發(fā)的挑戰(zhàn),微服務(wù)的架構(gòu)被廣泛使用,由于微服務(wù)架構(gòu)中應(yīng)用會(huì)被拆分成多個(gè)服務(wù)。

為了方便客戶端對(duì)這些服務(wù)的調(diào)用于是引入了 API 的概念。今天我們就來(lái)看看API 網(wǎng)關(guān)的原理以及它是如何應(yīng)用的。

API 網(wǎng)關(guān)的定義

網(wǎng)關(guān)一詞最早出現(xiàn)在網(wǎng)絡(luò)設(shè)備,比如兩個(gè)相互獨(dú)立的局域網(wǎng)之間通過(guò)路由器進(jìn)行通信, 中間的路由被稱之為網(wǎng)關(guān)。

落實(shí)在開發(fā)層面來(lái)說(shuō),就是客戶端與微服務(wù)系統(tǒng)之間存在的網(wǎng)關(guān)。從業(yè)務(wù)層面來(lái)說(shuō),當(dāng)客戶端完成某個(gè)業(yè)務(wù)的時(shí)候,需要同時(shí)調(diào)用多個(gè)微服務(wù)。

如圖 1 所示,當(dāng)客戶端發(fā)起下單請(qǐng)求需要調(diào)用:商品查詢、庫(kù)存扣減以及訂單更新等服務(wù)。

 

圖1 :API 網(wǎng)關(guān)加入前后對(duì)比

如果這些服務(wù)需要客戶端分別調(diào)用才能完成,會(huì)增加請(qǐng)求的復(fù)雜度,同時(shí)也會(huì)帶來(lái)網(wǎng)絡(luò)調(diào)用性能的損耗。因此,針對(duì)微服務(wù)的應(yīng)用場(chǎng)景就推出了 API 網(wǎng)關(guān)的調(diào)用。

在客戶端與微服務(wù)之間加入下單 API 網(wǎng)關(guān),客戶端直接給這個(gè) API 網(wǎng)關(guān)下達(dá)命令,由于后者完成對(duì)其他三個(gè)微服務(wù)的調(diào)用并且返回結(jié)果給客戶端。

從系統(tǒng)層面來(lái)說(shuō),任何一個(gè)應(yīng)用系統(tǒng)如果需要被其他系統(tǒng)調(diào)用,就需要暴露 API,這些 API 代表著的功能點(diǎn)。

正如上面下單的例子中提到的,如果一個(gè)下單的功能點(diǎn)需要調(diào)用多個(gè)服務(wù)的時(shí)候,在這個(gè)下單的 API 網(wǎng)關(guān)中就需要聚合多個(gè)服務(wù)的調(diào)用。

這個(gè)聚合的方式有點(diǎn)像設(shè)計(jì)模式中的門面模式(Facade),它為外部的調(diào)用提供了一個(gè)統(tǒng)一的訪問(wèn)入口。

不僅如此,如圖 2 所示,API 網(wǎng)關(guān)還可以協(xié)助兩個(gè)系統(tǒng)的通信,在系統(tǒng)之間加上一個(gè)中介者協(xié)助 API 的調(diào)用。

 

圖 2:對(duì)接兩個(gè)系統(tǒng)的 API 網(wǎng)關(guān)

從客戶端類型層面來(lái)說(shuō),為了屏蔽不同客戶端調(diào)用差異也可以加入 API 網(wǎng)關(guān)。

如圖 3 所示,在實(shí)際開發(fā)過(guò)程中 API 網(wǎng)關(guān)還可以根據(jù)不同的客戶端類型(iOS、Android、PC、小程序),提供不同的 API 網(wǎng)關(guān)與之對(duì)應(yīng)。

 

圖 3:對(duì)接客戶端和服務(wù)端的 API 網(wǎng)關(guān)

由于 API 網(wǎng)關(guān)所處的位置是客戶端與微服務(wù)交界的地方,因此從功能上它還包括:路由,負(fù)載均衡,限流,緩存,日志,發(fā)布等等。

Spring Cloud Gateway 概念與定義

API 網(wǎng)關(guān)的定義中我們提到了為什么要使用 API 網(wǎng)關(guān),是為了解決客戶端對(duì)多個(gè)微服務(wù)進(jìn)行訪問(wèn)的問(wèn)題。

由于服務(wù)的切分導(dǎo)致一個(gè)操作需要同時(shí)調(diào)用多個(gè)服務(wù),因此為這些服務(wù)的聚合提供一個(gè)統(tǒng)一的門面,這個(gè)門面就是 API 網(wǎng)關(guān)。

針對(duì)于 API 網(wǎng)關(guān)有很多的實(shí)現(xiàn)方式,例如:Zuul,Kong 等等。這里我們以及 Spring Cloud Gateway 為例展開給大家介紹其具體實(shí)現(xiàn)。

一般來(lái)說(shuō),API 網(wǎng)關(guān)對(duì)內(nèi)將微服務(wù)進(jìn)行集合,對(duì)外暴露的統(tǒng)一 URL 或者接口信息供客戶端調(diào)用。

那么客戶端是如何與微服務(wù)進(jìn)行連接,并且進(jìn)行溝通的,需要引入下面幾個(gè)重要概念 。

 

圖 4:路由、斷言和過(guò)濾器

如圖 4 所示,Spring Cloud Gateway 由三部分組成:

①路由(Route):任何一個(gè)來(lái)自于客戶端的請(qǐng)求都會(huì)經(jīng)過(guò)路由,然后到對(duì)應(yīng)的微服務(wù)中。

每個(gè)路由會(huì)有一個(gè)唯一的 ID 和對(duì)應(yīng)的目的 URL。同時(shí)包含若干個(gè)斷言(Predicate)和過(guò)濾器(Filter)。

②斷言(Predicate):當(dāng)客戶端通過(guò) Http Request 請(qǐng)求進(jìn)入 Spring Cloud Gateway 的時(shí)候,斷言會(huì)根據(jù)配置的路由規(guī)則,對(duì) Http Request 請(qǐng)求進(jìn)行斷言匹配。

說(shuō)白了就是進(jìn)行一次或者多次 if 判斷,如果匹配成功則進(jìn)行下一步處理,否則斷言失敗直接返回錯(cuò)誤信息。

③過(guò)濾器( Filter):簡(jiǎn)單來(lái)說(shuō)就是對(duì)流經(jīng)的請(qǐng)求進(jìn)行過(guò)濾,或者說(shuō)對(duì)其進(jìn)行獲取以及修改的操作。注意過(guò)濾器的功能是雙向的,也就是對(duì)請(qǐng)求和響應(yīng)都會(huì)進(jìn)行修改處理 。

一般來(lái)說(shuō) Spring Cloud Gateway 中的過(guò)濾器有兩種類型:

  • Gateway Filter
  • Global Filter

Gateway Filter 用在單個(gè)路由和分組路由上。Global Filter 可以作用于所有路由,是一個(gè)全局的 Filter。

Spring Cloud Gateway 工作原理

說(shuō)完了 Spring Cloud Gateway 定義和要素,再來(lái)看看其工作原理。總的來(lái)說(shuō)是對(duì)客戶端請(qǐng)求的處理過(guò)程。

 

圖 5:Spring Cloud Gateway 處理請(qǐng)求流程圖

如圖 5 所示,當(dāng)客戶端向 Spring Cloud Gateway 發(fā)起請(qǐng)求,該請(qǐng)求會(huì)被 HttpWebHandlerAdapter 獲取,并且對(duì)請(qǐng)求進(jìn)行提取,從而組裝成網(wǎng)關(guān)上下文。

將組成的上下文信息傳遞到 DispatcherHandler 組件。DispatcherHandler 作為請(qǐng)求分發(fā)處理器,主要負(fù)責(zé)將請(qǐng)求分發(fā)到對(duì)應(yīng)的處理器進(jìn)行處理。

這里請(qǐng)求的處理器包括 RoutePredicate HandlerMapping (路由斷言處理映射器) 。

路由斷言處理映射器用于路由的查找,以及找到 路由后返回對(duì)應(yīng)的 FilteringWebHandler。

其負(fù)責(zé)組裝 Filter 鏈表并執(zhí)行過(guò)濾處理,之后再將請(qǐng)求轉(zhuǎn)交給應(yīng)用服務(wù),應(yīng)用服務(wù)處理完后,最后返回 Response 給客戶端 。

其中 FilteringWebHandler 處理請(qǐng)求的時(shí)候會(huì)交給 Filter 進(jìn)行過(guò)濾的處理。

這里需要注意的是由于 Filter 是雙向的所以,當(dāng)客戶端請(qǐng)求服務(wù)的時(shí)候,會(huì)通過(guò) Pre Filter 中的 Filter 處理請(qǐng)求。

當(dāng)服務(wù)處理完請(qǐng)求以后返回客戶端的時(shí)候,會(huì)通過(guò) Post Filter 再進(jìn)行一次處理。

Spring Cloud Gateway 最佳實(shí)踐

上面介紹了 Spring Cloud Gateway 的定義和實(shí)現(xiàn)原理,下面根據(jù)幾個(gè)常用的場(chǎng)景介紹一下 Spring Cloud Gateway 如何實(shí)現(xiàn)網(wǎng)關(guān)功能的。

我們會(huì)根據(jù)基本路由、權(quán)重路由、限流、動(dòng)態(tài)路由幾個(gè)方面給大家展開介紹。

基本路由

基本路由,主要功能就是在客戶端請(qǐng)求的時(shí)候,根據(jù)定義好的路徑指向到對(duì)應(yīng)的 URI。這個(gè)過(guò)程中需要用到 Predicates(斷言)中的 Path 路由斷言處理器。

首先在 POM 文件中加入對(duì)應(yīng)的依賴,如下:

  1. <dependency> 
  2.     <groupId>org.springframework.cloud</groupId> 
  3.     <artifactId>spring-cloud-starter-gateway</artifactId> 
  4. </dependency> 

加入如下代碼,其中定義的 Path 的路徑“/baidu”就是請(qǐng)求時(shí)的路徑地址。對(duì)應(yīng)的 URI,http://www.baidu.com/ 就是要跳轉(zhuǎn)到的目標(biāo)地址。

  1. @Bean 
  2. public RouteLocator routeLocator(RouteLocatorBuilder builder) { 
  3.    return builder.routes() 
  4.          .route(r ->r.path("/baidu"
  5.                .uri("http://www.baidu.com/").id("baidu_route"
  6.          ).build(); 

同樣上面的功能也可以在 yml 文件中實(shí)現(xiàn)。配置文件如下,說(shuō)白了就是對(duì) Path 和 URI 參數(shù)的設(shè)置,實(shí)現(xiàn)的功能和上面代碼保持一致。

  1. spring: 
  2.   cloud: 
  3.     gateway: 
  4.       routes: 
  5.       - id: baidu_route 
  6.         uri: http://baidu.com:80/ 
  7.         predicates: 
  8.         - Path=/baidu 

此時(shí)啟動(dòng) API 網(wǎng)關(guān),假設(shè)網(wǎng)關(guān)的訪問(wèn)地址是“localhost:8080/baidu”,當(dāng)用戶請(qǐng)求這個(gè)地址的時(shí)候就會(huì)自動(dòng)請(qǐng)求“www.baidu.com”這個(gè)網(wǎng)站。這個(gè)配置起來(lái)很簡(jiǎn)單,有 Nginx 基礎(chǔ)的朋友應(yīng)該很快就能上手。

權(quán)重路由

這個(gè)使用場(chǎng)景相對(duì)于上面的簡(jiǎn)單路由要多一些。由于每個(gè)微服務(wù)發(fā)布新版本的時(shí)候,通常會(huì)保持老版本與新版版同時(shí)存在。

然后通過(guò)網(wǎng)關(guān)將流量逐步從老版本的服務(wù)切換到新版本的服務(wù)。這個(gè)逐步切換的過(guò)程就是常說(shuō)的灰度發(fā)布。

此時(shí),API 網(wǎng)關(guān)就起到了流量分發(fā)的作用,通常來(lái)說(shuō)最開始的老版本會(huì)承載多一些的流量,例如 90% 的請(qǐng)求會(huì)被路由到老版本的服務(wù)上,只有 10% 的請(qǐng)求會(huì)路由到新服務(wù)上去。

從而觀察新服務(wù)的穩(wěn)定性,或者得到用戶的反饋。當(dāng)新服務(wù)穩(wěn)定以后,再將剩下的流量一起導(dǎo)入過(guò)去。

 

圖 6:灰度發(fā)布,路由到新/老服務(wù)

如下代碼所示,假設(shè) API 網(wǎng)關(guān)還是采用 8080 端口,需要針對(duì)兩個(gè)不同的服務(wù)配置路由權(quán)重。因此在 routes 下面分別配置 service_old 和 service_new。

  1. server.port: 8080 
  2. spring: 
  3.   application: 
  4.     name: gateway-test 
  5.   cloud: 
  6.     gateway: 
  7.       routes: 
  8.       - id: service_old 
  9.         uri: http://localhost:8888/v1 
  10.         predicates: 
  11.         - Path=/gatewaytest 
  12.         - Weight=service, 90 
  13.       - id: service_new 
  14.         uri: http://localhost:8888/v2 
  15.         predicates: 
  16.         - Path=/gatewaytest 
  17.         - Weight=service, 10 

在兩個(gè)配置中對(duì)應(yīng)的 URI 分別是新老兩個(gè)服務(wù)的訪問(wèn)地址,通過(guò)“http://localhost:8888/v1”和“http://localhost:8888/v2”來(lái)區(qū)別。

在 Predicates(斷言)中定義了的 Path 是想通的都是“/gatewaytest”,也就是說(shuō)對(duì)于客戶端來(lái)說(shuō)訪問(wèn)的路徑都是一樣的,從路徑上客戶不會(huì)感知他們?cè)L問(wèn)的是新服務(wù)或者是老服務(wù)。

主要參數(shù)是在 Weight,針對(duì)老/新服務(wù)分別配置的是 90 和 10。也就是有 90% 的流量會(huì)請(qǐng)求老服務(wù),有 10% 的流量會(huì)請(qǐng)求新服務(wù)。

簡(jiǎn)單點(diǎn)說(shuō),如果有 100 次請(qǐng)求,其中 90 次會(huì)請(qǐng)求 v1(老服務(wù)),另外的 10 次會(huì)請(qǐng)求 v2(新服務(wù))。

限流

當(dāng)服務(wù)在短時(shí)間內(nèi)迎來(lái)高并發(fā),并發(fā)量超過(guò)服務(wù)承受的范圍就需要使用限流。例如:秒殺、搶購(gòu)、下單服務(wù)。

通過(guò)請(qǐng)求限速或者對(duì)一個(gè)時(shí)間窗口內(nèi)的請(qǐng)求進(jìn)行限速來(lái)保護(hù)服務(wù)。當(dāng)達(dá)到限制速率則可以拒絕請(qǐng)求,返回錯(cuò)誤代碼,或者定向到友好頁(yè)面。

一般的中間件都會(huì)有單機(jī)限流框架,支持兩種限流模式:

  • 控制速率
  • 控制并發(fā)

這里通過(guò) Guava 中的 Bucket4j 來(lái)實(shí)現(xiàn)限流操作。按照慣例引入 Bucket4j 的依賴:

  1. <dependency> 
  2.     <groupId>com.github.vladimir-bukhtoyarov</groupId> 
  3.     <artifactId>bucket4j-core</artifactId> 
  4.     <version>4.0.0</version> 
  5. </dependency> 

由于需要對(duì)于用戶請(qǐng)求進(jìn)行監(jiān)控,因此通過(guò)實(shí)現(xiàn) GatewayFilter 的方式自定義 Filter,然后再通過(guò) Gateway API Application 應(yīng)用這個(gè)自定義的 Filter。

這里我們使用的是令牌桶的方式進(jìn)行限流,因此需要設(shè)置桶的容量(capacity),每次填充的令牌數(shù)量(refillTokens)以及填充令牌的間隔時(shí)間(refillDuration)。

初始化這三個(gè)參數(shù)以后,通過(guò) createNewBucket 方法針對(duì)請(qǐng)求建立令牌桶(bucket),在 Filter 方法中實(shí)現(xiàn)限流的主要邏輯。

通過(guò) ServerWebExchange 獲取請(qǐng)求的上下文中的 IP 信息,針對(duì) IP 建立對(duì)應(yīng)的令牌桶,這個(gè) IP 與令牌桶的對(duì)應(yīng)關(guān)系放到了 LOCAL_CACHE 中。

每次請(qǐng)求經(jīng)過(guò)的時(shí)候通過(guò) tryConsume(1) 方法消費(fèi)一個(gè)令牌,直到?jīng)]有令牌的時(shí)候返回 HttpStatus.TOO_MANY_REQUESTS 的狀態(tài)碼(429),此時(shí)網(wǎng)關(guān)直接返回請(qǐng)求次數(shù)太多,即便是再有請(qǐng)求進(jìn)來(lái)也不會(huì)路由到對(duì)應(yīng)的服務(wù)了。

只有等待下一個(gè)時(shí)間間隔,一定數(shù)量的令牌放到桶里的時(shí)候,請(qǐng)求拿到桶中的令牌才能再次請(qǐng)求服務(wù)。

  1. public class GatewayRateLimitFilterByIp implements GatewayFilter, Ordered { 
  2.     private static final Map<String, Bucket> LOCAL_CACHE = new ConcurrentHashMap<>(); 
  3.     int capacity; 
  4.     int refillTokens; 
  5.     Duration refillDuration; 
  6.     public GatewayRateLimitFilterByIp() { 
  7.     } 
  8.  
  9.     public GatewayRateLimitFilterByIp(int capacity, int refillTokens, Duration refillDuration) { 
  10.         this.capacity = capacity; 
  11.         this.refillTokens = refillTokens; 
  12.         this.refillDuration = refillDuration; 
  13.     } 
  14.  
  15.     private Bucket createNewBucket() { 
  16.         Refill refill = Refill.of(refillTokens, refillDuration); 
  17.         Bandwidth limit = Bandwidth.classic(capacity, refill); 
  18.         return Bucket4j.builder().addLimit(limit).build(); 
  19.     } 
  20.  
  21.     @Override 
  22.     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { 
  23.         String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); 
  24.         Bucket bucket = LOCAL_CACHE.computeIfAbsent(ip, k -> createNewBucket()); 
  25.         if (bucket.tryConsume(1)) { 
  26.             return chain.filter(exchange); 
  27.         } else { 
  28. exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); 
  29.             return exchange.getResponse().setComplete(); 
  30.         } 
  31.     } 

上面的代碼定義了 Filter 其中針對(duì)訪問(wèn)的 IP 生成令牌桶,并且定義了桶的大小、每次放入桶令牌的個(gè)數(shù)、放入令牌的間隔時(shí)間。

并且通過(guò) Filter 方法重寫了過(guò)濾的邏輯,那么下面只需要將這個(gè) Filter 應(yīng)用到 Spring Cloud Gateway 的規(guī)則上去就可以了。通過(guò)下面代碼定義網(wǎng)關(guān)的路由斷言和過(guò)濾器。

在 Filters 中新建一個(gè)上面代碼定義的過(guò)濾器,指定容量是 20,每?jī)擅敕湃肓钆疲看畏湃胍粋€(gè)令牌。

那么當(dāng)用戶訪問(wèn) rateLimit 路徑的時(shí)候就會(huì)根據(jù)客制化的 Filter 進(jìn)行限流。

  1. @Bean 
  2. public RouteLocator testRouteLocator(RouteLocatorBuilder builder) { 
  3.     return builder.routes() 
  4.             .route(r -> r.path("/rateLimit"
  5.                     .filters(f -> f.filter(new GatewayRateLimitFilterByIp(20,1,Duration.ofSeconds(2)))) 
  6.                     .uri("http://localhost:8888/rateLimit"
  7.                     .id("rateLimit_route"
  8.             ).build(); 

這里的限流只是給大家提供一種思路,通過(guò)實(shí)現(xiàn) GatewayFilter,重寫其中的 Filter 方法,加入對(duì)流量的控制代碼,然后在 Spring Cloud Gateway 中進(jìn)行應(yīng)用就可以了。

動(dòng)態(tài)路由

由于 Spring Cloud Gateway 本身也是一個(gè)服務(wù),一旦啟動(dòng)以后路由配置就無(wú)法修改了。

無(wú)論是上面提到的編碼注入的方式還是配置的方式,如果需要修改都需要重新啟動(dòng)服務(wù)。

如果回到 Spring Cloud Gateway 最初的定義,我們會(huì)發(fā)現(xiàn)每個(gè)用戶的請(qǐng)求都是通過(guò) Route 訪問(wèn)對(duì)應(yīng)的微服務(wù),在 Route 中包括 Predicates 和 Filters 的定義。

只要實(shí)現(xiàn) Route 以及其包含的 Predicates 和 Filters 的定義,然后再提供一個(gè) API 接口去更新這個(gè)定義就可以動(dòng)態(tài)地修改路由信息了。

按照這個(gè)思路需要做以下幾步來(lái)實(shí)現(xiàn):

①定義 Route、Predicates 和 Filters

其中 Predicates 和 Filters 包含在 Route 中。實(shí)際上就是 Route 實(shí)體的定義,針對(duì) Route 進(jìn)行路由規(guī)則的配置。

  1. public class FilterDefinition { 
  2.     //Filter Name 
  3.     private String name
  4.     //對(duì)應(yīng)的路由規(guī)則 
  5.     private Map<String, String> args = new LinkedHashMap<>(); 
  6. public class PredicateDefinition { 
  7.     //Predicate Name 
  8.     private String name
  9.     //對(duì)應(yīng)的斷言規(guī)則 
  10.     private Map<String, String> args = new LinkedHashMap<>(); 
  11. public class RouteDefinition { 
  12.     //斷言集合 
  13. private List<PredicateDefinition> predicates = new ArrayList<>(); 
  14. //路由集合 
  15. private List< FilterDefinition > filters= new ArrayList<>(); 
  16. //uri 
  17. private String uri; 
  18. //執(zhí)行次序 
  19. private int order = 0; 

②實(shí)現(xiàn)路由規(guī)則的操作,包括添加,更新,刪除

有了路由的定義(Route,Predicates,F(xiàn)ilters),然后再編寫針對(duì)路由定義的操作。

例如:添加路由,刪除路由,更新路由之類的。編寫 RouteServiceImpl 實(shí)現(xiàn) ApplicationEventPublisherAware。

主要需要 override 其中的 setApplicationEventPublisher 方法,這里會(huì)傳入 ApplicationEventPublisher 對(duì)象,通過(guò)這個(gè)對(duì)象發(fā)布路由定義的事件包括:add,update,delete。

貼出部分代碼如下:

  1. @Service 
  2. public class RouteServiceImpl implements ApplicationEventPublisherAware { 
  3.     @Autowired 
  4.     private RouteDefinitionWriter routeDefinitionWriter; 
  5.     private ApplicationEventPublisher publisher; 
  6.     //添加路由規(guī)則 
  7.     public String add(RouteDefinition definition) { 
  8.         routeDefinitionWriter.save(Mono.just(definition)).subscribe(); 
  9.         this.publisher.publishEvent(new RefreshRoutesEvent(this)); 
  10.         return "success"
  11.     } 
  12.     public String update(RouteDefinition definition) { 
  13.         try { 
  14.           this.routeDefinitionWriter.delete(Mono.just(definition.getId())); 
  15.         } catch (Exception e) { 
  16.  
  17.         } 
  18.         try { 
  19.             routeDefinitionWriter.save(Mono.just(definition)).subscribe(); 
  20.             this.publisher.publishEvent(new RefreshRoutesEvent(this)); 
  21.             return "success"
  22.         } catch (Exception e) { 
  23.  
  24.         } 
  25.     } 
  26.     public String delete(String id) { 
  27.         try { 
  28.             this.routeDefinitionWriter.delete(Mono.just(id)); 
  29.             return "delete success"
  30.         } catch (Exception e) { 
  31.  
  32.         } 
  33.  
  34.     } 
  35.  
  36.     @Override 
  37.     public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { 
  38.         this.publisher = applicationEventPublisher; 
  39.     } 

③對(duì)外部提供 API 接口能夠讓用戶或者程序動(dòng)態(tài)修改路由規(guī)則

從代碼上來(lái)說(shuō)就是一個(gè) Controller。這個(gè) Controller 中只需要調(diào)用 routeServiceImpl 就行了,主要也是用到客制化路由實(shí)現(xiàn)類中的 add,update,delete 方法。

說(shuō)白了就是對(duì)其進(jìn)行了一次包裝,讓外部系統(tǒng)可以調(diào)用,并且修改路由的配置。

經(jīng)過(guò)簡(jiǎn)化以后的代碼如下,這里只對(duì) add 方法進(jìn)行了包裝,關(guān)于 update 和 delete 方法在這里不展開說(shuō)明,調(diào)用方式類似 add。

  1. public class RouteController { 
  2.  
  3.     @Autowired 
  4.     private routeServiceImpl routeService; 
  5.  
  6.     @PostMapping("/add"
  7.     public String add(@RequestBody RouteDefinition routeDefinition) { 
  8.         try { 
  9.             RouteDefinition definition = assembleRouteDefinition(routeDefinition); 
  10.             return this.dynamicRouteService.add(definition); 
  11.         } catch (Exception e) { 
  12.                    } 
  13.         return "succss"
  14.     } 

④啟動(dòng)程序進(jìn)行路由的添加和更新操作

假設(shè)更新 API 網(wǎng)關(guān)配置的服務(wù)在 8888 端口上。于是通過(guò) http://localhost:8888/actuator/gateway/routes 訪問(wèn)當(dāng)前的路由信息,由于現(xiàn)在沒(méi)有配置路由這個(gè)信息是空。

那么通過(guò) http://localhost:8888/route/add 方式添加一條路由規(guī)則,這里選擇 Post 請(qǐng)求,輸入類型為 Json 如下:

  1.     "filter":[], 
  2.     "id":"baidu_route"
  3.     "order":0, 
  4.     "predicates":[{ 
  5.         "args":{ 
  6.             "pattern":"/baidu" 
  7.         }, 
  8.         "name":"Path" 
  9.     }], 
  10.     "uri":"https://www.baidu.com" 

Json 中配置的內(nèi)容和簡(jiǎn)單路由配置的內(nèi)容非常相似。設(shè)置了 Route,當(dāng) Predicates 為 baidu 的時(shí)候,將請(qǐng)求引導(dǎo)到 www.baidu.com 的網(wǎng)站進(jìn)行響應(yīng)。

此時(shí)再通過(guò)訪問(wèn) http://localhost:8888/baidu 的路徑訪問(wèn)的時(shí)候,就會(huì)被路由到 www.baidu.com 的網(wǎng)站。

此時(shí)如果需要修改路由配置,可以通過(guò)訪問(wèn) http://localhost:8888/route/update 的 API 接口,通過(guò) Post 方式傳入 Json 結(jié)構(gòu),例如:

  1.     "filter":[], 
  2.     "id":"CTO_route"
  3.     "order":0, 
  4.     "predicates":[{ 
  5.         "args":{ 
  6.             "pattern":"/CTO" 
  7.         }, 
  8.         "name":"Path" 
  9.     }], 
  10.     "uri":"http://www.ekrvqnd.cn" 

在更新完成以后,再訪問(wèn) http://localhost:8888/CTO 的時(shí)候就會(huì)把引導(dǎo)到 www.ekrvqnd.cn 的網(wǎng)站了。

通過(guò)上面四步操作,即使不重啟 Spring Cloud Gateway 服務(wù)也可以動(dòng)態(tài)更改路由的配置信息。

總結(jié)

由于微服務(wù)的盛行,API 網(wǎng)關(guān)悄然興起。針對(duì) API 網(wǎng)關(guān)本身講述了其存在的原因,它不僅提供了服務(wù)的門面,而且可以協(xié)調(diào)不同的系統(tǒng)之間的通訊以及服務(wù)不同的客戶端接口。

針對(duì) API 網(wǎng)關(guān)的最佳時(shí)間 Spring Cloud Gateway 的定義和概念的解釋,其實(shí)現(xiàn)了路由、過(guò)濾器、斷言,針對(duì)不同的客戶端請(qǐng)求可以路由到不同的微服務(wù),以及其中幾個(gè)組件是如何分工合作完成路由工作的。

在最佳實(shí)踐的介紹中分別從:基本路由、權(quán)重路由、限流和動(dòng)態(tài)路由幾個(gè)方面進(jìn)行了闡述。

【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為51CTO.com】

 

責(zé)任編輯:武曉燕 來(lái)源: 51CTO技術(shù)棧
相關(guān)推薦

2021-03-16 15:12:57

CompletableFuture機(jī)制java

2022-02-22 08:25:51

typeScript泛型概念泛型使用

2024-09-09 08:36:36

Java操作遠(yuǎn)程服務(wù)器

2024-08-12 12:25:25

SpringMVC開發(fā)

2020-09-01 14:17:03

WindowsDefender微軟

2020-10-21 10:02:16

架構(gòu)運(yùn)維技術(shù)

2020-09-27 06:50:56

Java互聯(lián)網(wǎng)注解

2019-09-03 09:30:46

ss 命令SocketLinux

2020-09-15 09:50:47

程序員技能開發(fā)者

2020-12-18 09:45:33

DockerLinux命令

2020-08-26 14:40:38

explainMySQL數(shù)據(jù)庫(kù)

2022-08-01 08:17:46

mysqlwindows系統(tǒng)

2020-11-09 09:03:35

高并發(fā)多線程ThreadLocal

2012-05-02 15:38:49

金山快盤網(wǎng)盤

2022-11-18 17:36:38

Spring架構(gòu)

2022-08-12 15:58:34

Docker

2019-11-28 16:48:00

華為Mate X

2022-11-07 17:50:36

2018-09-13 10:40:40

Linux命令find

2020-12-07 09:15:00

JavaScript數(shù)組 reduce
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 五月综合激情在线 | 99热热99| 精品久久久久久久久久 | 国产精品美女久久久久久不卡 | 啪一啪| 天天人人精品 | 日韩视频一区二区 | 日日夜夜狠狠操 | 涩涩视频网 | 91精品国产综合久久精品图片 | 99久久夜色精品国产亚洲96 | 欧美一区二区在线播放 | 亚洲视频精品 | 欧美日韩一卡二卡 | www成年人视频 | 成人欧美一区二区三区 | 国外成人在线视频 | 99久久日韩精品免费热麻豆美女 | 欧美日韩美女 | 超碰520| 久久不射电影网 | 中国黄色毛片视频 | 视频在线h | 在线一区二区三区 | 国产精品久久久久久久久图文区 | 亚洲一区二区 | 亚洲精品区 | 亚洲精品一 | 中文字幕一区二区三区乱码图片 | 草比网站 | 日本久草 | 一区二区在线免费播放 | 日韩精品中文字幕一区二区三区 | 深夜福利影院 | 一区二区三区网站 | 久久久久久久久久久久一区二区 | 国产精品夜间视频香蕉 | 精品99久久久久久 | 中文字幕韩在线第一页 | 亚洲欧美在线视频 | 日韩欧美国产一区二区 |