<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          限流10萬QPS、跨域、過濾器、令牌桶算法-網關Gateway內容柒哥都給你總結在這兒了

          共 6772字,需瀏覽 14分鐘

           ·

          2020-12-11 13:34

          程序員的成長之路
          互聯(lián)網/程序員/技術/資料共享?
          關注


          閱讀本文大概需要 7 分鐘。

          作者:雄哥666
          https://juejin.im/post/6895201419805392909

          一、微服務網關Spring Cloud Gateway

          1.1 導引

          文中內容包含:微服務網關限流10萬QPS、跨域、過濾器、令牌桶算法。
          在構建微服務系統(tǒng)中,必不可少的技術就是網關了,從早期的Zuul,到現在的Spring Cloud Gateway,網關我們用的不可少。
          今天我就將沉淀下來的所有與網關相關的知識,用一篇文章總結清楚,希望對愛學習的小伙伴們有所幫助。
          本篇文章主要介紹網關跨域配置,網關過濾器編寫,網關的令牌桶算法限流【每秒10萬QPS】
          首先我們來看什么是網關

          1.2 什么是微服務網關Gateway?

          This project provides a library for building an API Gateway on top of Spring WebFlux.
          gateway官網:
          https://spring.io/projects/spring-cloud-gateway
          實現微服務網關的技術有很多,
          • nginx ?Nginx (engine x) 是一個高性能的HTTP和反向代理web服務器,同時也提供了IMAP/POP3/SMTP服務

          • zuul ,Zuul 是 Netflix 出品的一個基于 JVM 路由和服務端的負載均衡器。

          • spring-cloud-gateway, 是spring 出品的 基于spring 的網關項目,集成斷路器,路徑重寫,性能比Zuul好。

          我們使用gateway這個網關技術,無縫銜接到基于spring cloud的微服務開發(fā)中來。

          1.3 微服務為什么要使用網關呢?

          不同的微服務一般會有不同的網絡地址,而外部客戶端可能需要調用多個服務的接口才能完成一個業(yè)務需求,如果讓客戶端直接與各個微服務通信,會有以下的問題:
          1. 客戶端會多次請求不同的微服務,增加了客戶端的復雜性

          2. 存在跨域請求,在一定場景下處理相對復雜

          3. 認證復雜,每個服務都需要獨立認證

          4. 難以重構,隨著項目的迭代,可能需要重新劃分微服務。例如,可能將多個服務合并成一個或者將一個服務拆分成多個。如果客戶端直接與微服務通信,那么重構將會很難實施

          5. 某些微服務可能使用了防火墻 / 瀏覽器不友好的協(xié)議,直接訪問會有一定的困難

          以上這些問題可以借助網關解決。
          網關是介于客戶端和服務器端之間的中間層,所有的外部請求都會先經過 網關這一層。也就是說,API 的實現方面更多的考慮業(yè)務邏輯,而安全、性能、監(jiān)控可以交由 網關來做,這樣既提高業(yè)務靈活性又不缺安全性,典型的架構圖如圖所示:

          1.4 微服務網關優(yōu)點

          • 安全 ,只有網關系統(tǒng)對外進行暴露,微服務可以隱藏在內網,通過防火墻保護。

          • 易于監(jiān)控??梢栽诰W關收集監(jiān)控數據并將其推送到外部系統(tǒng)進行分析。

          • 易于認證??梢栽诰W關上進行認證,然后再將請求轉發(fā)到后端的微服務,而無須在每個微服務中進行認證。

          • 減少了客戶端與各個微服務之間的交互次數

          • 易于統(tǒng)一授權。

          1.5 總結

          微服務網關就是一個系統(tǒng),通過暴露該微服務網關系統(tǒng),方便我們進行相關的鑒權,安全控制,日志統(tǒng)一處理,易于監(jiān)控的相關功能。歷史文章:200期階段匯總

          二、微服務網關搭建及配置

          2.1 微服務網關微服務搭建

          由于我們開發(fā)的系統(tǒng) 有包括前臺系統(tǒng)和后臺系統(tǒng),后臺的系統(tǒng)給管理員使用。那么也需要調用各種微服務,所以我們針對管理后臺搭建一個網關微服務。分析如下:
          搭建步驟:
          (1)依賴坐標pom.xml:

          <dependency>
          ????<groupId>org.springframework.cloudgroupId>
          ????<artifactId>spring-cloud-starter-gatewayartifactId>
          dependency>
          <dependency>
          ????<groupId>org.springframework.cloudgroupId>
          ????<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
          dependency>
          <dependency>
          ????<groupId>org.springframework.cloudgroupId>
          ????<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
          dependency>

          (2)啟動引導類:GatewayApplication

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

          (3)在resources下創(chuàng)建application.yml

          spring:
          ??application:
          ????name:?apigateway
          ??cloud:
          ????gateway:
          ??????routes:
          ??????-?id:?open
          ????????uri:?lb://open
          ????????predicates:
          ????????-?Path=/open/**
          ????????filters:
          ????????-?StripPrefix=?1
          ??????-?id:?system
          ????????uri:?lb://system
          ????????predicates:
          ????????-?Path=/system/**
          ????????filters:
          ????????-?StripPrefix=?1
          server:
          ??port:?9999
          eureka:
          ??client:
          ????service-url:
          ??????defaultZone:?http://127.0.0.1:10086/eureka
          ??instance:
          ????prefer-ip-address:?true

          參考官方手冊:
          https://cloud.spring.io/spring-cloud-gateway/spring-cloud-gateway.html#_stripprefix_gatewayfilter_factory

          2.2 微服務網關跨域

          在啟動類GatewayApplication中,加入跨域配置代碼如下

          @Bean
          public?CorsWebFilter?corsFilter()?{
          ????CorsConfiguration?config?=?new?CorsConfiguration();
          ????config.addAllowedMethod("*");//支持所有方法
          ????config.addAllowedOrigin("*");//跨域處理?允許所有的域
          ????config.addAllowedHeader("*");//支持所有請求頭

          ????UrlBasedCorsConfigurationSource?source?=?new?UrlBasedCorsConfigurationSource(new?PathPatternParser());
          ????source.registerCorsConfiguration("/**",?config);//匹配所有請求

          ????return?new?CorsWebFilter(source);
          }

          三、微服務網關過濾器

          我們可以通過網關過濾器,實現一些邏輯的處理,比如ip黑白名單攔截、特定地址的攔截等。下面的代碼中做了兩個過濾器,并且設定的先后順序。
          (1)在網關微服務中創(chuàng)建IpFilter,無需配置其他,注冊到Spring容器即可生效

          @Component
          public?class?IpFilter?implements?GlobalFilter,?Ordered?{

          ????@Override
          ????public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)?{
          ????????ServerHttpRequest?request?=?exchange.getRequest();
          ????????InetSocketAddress?remoteAddress?=?request.getRemoteAddress();
          ????????//TODO?設置ip白名單
          ????????System.out.println("ip:"+remoteAddress.getHostName());
          ????????return?chain.filter(exchange);
          ????}
          ????@Override
          ????public?int?getOrder()?{
          ????????return?1;
          ????}
          }

          (2)在網關微服務中創(chuàng)建UrlFilter,無需配置其他,注冊到Spring容器即可生效

          @Component
          public?class?UrlFilter?implements?GlobalFilter,?Ordered?{

          ????@Override
          ????public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)?{
          ????????ServerHttpRequest?request?=?exchange.getRequest();
          ????????String?url?=?request.getURI().getPath();
          ????????//TODO?攔截特定URL地址
          ????????System.out.println("url:"+url);
          ????????return?chain.filter(exchange);
          ????}

          ????@Override
          ????public?int?getOrder()?{
          ????????return?2;
          ????}
          }

          四、網關限流每秒10萬請求

          我們之前說過,網關可以做很多的事情,比如,限流,當我們的系統(tǒng) 被頻繁的請求的時候,就有可能 將系統(tǒng)壓垮,所以 為了解決這個問題,需要在每一個微服務中做限流操作,但是如果有了網關,那么就可以在網關系統(tǒng)做限流,因為所有的請求都需要先通過網關系統(tǒng)才能路由到微服務中。

          4.1 限流實現思路分析

          看圖就完了,非常簡單!

          4.2 令牌桶算法 介紹

          令牌桶算法是比較常見的限流算法之一,大概描述如下:
          1)所有的請求在處理之前都需要拿到一個可用的令牌才會被處理;
          2)根據限流大小,設置按照一定的速率往桶里添加令牌;
          3)桶設置最大的放置令牌限制,當桶滿時、新添加的令牌就被丟棄或者拒絕;
          4)請求達到后首先要獲取令牌桶中的令牌,拿著令牌才可以進行其他的業(yè)務邏輯,處理完業(yè)務邏輯之后,將令牌直接刪除;
          5)令牌桶有最低限額,當桶中的令牌達到最低限額的時候,請求處理完之后將不會刪除令牌,以此保證足夠的限流
          如下圖:
          這個算法的實現,有很多技術,Guava(讀音: 瓜哇)是其中之一,redis客戶端也有其實現。歷史文章:200期階段匯總

          4.3 網關限流代碼實現

          需求:每個ip地址1秒內只能發(fā)送10萬請求,多出來的請求返回429錯誤。
          代碼實現:
          (1)spring cloud gateway 默認使用redis的RateLimter限流算法來實現。所以我們要使用首先需要引入redis的依賴


          <dependency>
          ????<groupId>org.springframework.bootgroupId>
          ????<artifactId>spring-boot-starter-data-redis-reactiveartifactId>
          ????<version>2.1.3.RELEASEversion>
          dependency>

          (2)定義KeyResolver
          在GatewayApplicatioin引導類中添加如下代碼,KeyResolver用于計算某一個類型的限流的KEY也就是說,可以通過KeyResolver來指定限流的Key。

          ????//定義一個KeyResolver
          ????@Bean
          ????public?KeyResolver?ipKeyResolver()?{
          ????????return?new?KeyResolver()?{
          ????????????@Override
          ????????????public?Mono?resolve(ServerWebExchange?exchange)?{
          ????????????????return?Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
          ????????????}
          ????????};
          ????}

          (3)修改application.yml中配置項,指定限制流量的配置以及REDIS的配置,修改后最終配置如下:

          spring:
          ??application:
          ????name:?apigateway
          ??cloud:
          ????gateway:
          ??????routes:
          ??????-?id:?open
          ????????uri:?lb://open
          ????????predicates:
          ????????-?Path=/open/**
          ????????filters:
          ????????-?StripPrefix=?1
          ????????-?name:?RequestRateLimiter?#請求數限流?名字不能隨便寫?
          ??????????args:
          ????????????key-resolver:?"#{@ipKeyResolver}"
          ????????????redis-rate-limiter.replenishRate:?1
          ????????????redis-rate-limiter.burstCapacity:?1
          ??????-?id:?system
          ????????uri:?lb://system
          ????????predicates:
          ????????-?Path=/system/**
          ????????filters:
          ????????-?StripPrefix=?1
          ??#?配置Redis?127.0.0.1可以省略配置
          ??redis:
          ????host:?101.57.2.128
          ????port:?6379
          server:
          ??port:?9999
          eureka:
          ??client:
          ????service-url:
          ??????defaultZone:?http://127.0.0.1:100/eureka
          ??instance:
          ????prefer-ip-address:?true

          解釋:
          • burstCapacity:令牌桶總容量。

          • replenishRate:令牌桶每秒填充平均速率。

          • key-resolver:用于限流的鍵的解析器的 Bean 對象的名字。它使用 SpEL 表達式根據#{@beanName}從 Spring 容器中獲取 Bean 對象。

          通過在replenishRate和中設置相同的值來實現穩(wěn)定的速率burstCapacity。設置burstCapacity高于時,可以允許臨時突發(fā)replenishRate。在這種情況下,需要在突發(fā)之間允許速率限制器一段時間(根據replenishRate),因為2次連續(xù)突發(fā)將導致請求被丟棄(HTTP 429 - Too Many Requests
          key-resolver: "#{@userKeyResolver}" 用于通過SPEL表達式來指定使用哪一個KeyResolver.
          如上配置:
          表示 一秒內,允許 一個請求通過,令牌桶的填充速率也是一秒鐘添加一個令牌。
          最大突發(fā)狀況 也只允許 一秒內有一次請求,可以根據業(yè)務來調整 。
          (4)測試時需要注意服務啟動順序,這里需要依賴于Redis,所以首先要啟動redis
          • 啟動redis

          • 啟動注冊中心

          • 啟動商品微服務

          • 啟動gateway網關

          • 打開瀏覽器 ?http://localhost:9999/open

          • 快速刷新,當1秒內發(fā)送超過10萬次請求,就會返回429錯誤。

          推薦閱讀:

          面試官:String長度有限制嗎?是多少?還好我看過

          男子一口氣充了90年愛奇藝會員被刑拘,以后還敢薅羊毛嗎?

          5T技術資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機,樹莓派,等等。在公眾號內回復「2048」,即可免費獲?。?!

          微信掃描二維碼,關注我的公眾號

          朕已閱?

          瀏覽 24
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美日韩777 | 草逼无码| 欧美日韩中文字幕在线观看 | 操比视频99 | 欧美激情爱爱网址 |