<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萬(wàn)QPS、跨域、過濾器、令牌桶算法-網(wǎng)關(guān)Gateway內(nèi)容都在這兒

          共 6761字,需瀏覽 14分鐘

           ·

          2020-11-23 11:47

          點(diǎn)擊上方?好好學(xué)java?,選擇?星標(biāo)?公眾號(hào)

          重磅資訊、干貨,第一時(shí)間送達(dá)

          今日推薦:硬剛一周,3W字總結(jié),一年的經(jīng)驗(yàn)告訴你如何準(zhǔn)備校招!

          個(gè)人原創(chuàng)100W+訪問量博客:點(diǎn)擊前往,查看更多

          作者:雄哥666

          https://juejin.im/post/6895201419805392909

          一、微服務(wù)網(wǎng)關(guān)Spring Cloud Gateway

          1.1 導(dǎo)引

          文中內(nèi)容包含:微服務(wù)網(wǎng)關(guān)限流10萬(wàn)QPS、跨域、過濾器、令牌桶算法。

          在構(gòu)建微服務(wù)系統(tǒng)中,必不可少的技術(shù)就是網(wǎng)關(guān)了,從早期的Zuul,到現(xiàn)在的Spring Cloud Gateway,網(wǎng)關(guān)我們用的不可少。

          今天我就將沉淀下來(lái)的所有與網(wǎng)關(guān)相關(guān)的知識(shí),用一篇文章總結(jié)清楚,希望對(duì)愛學(xué)習(xí)的小伙伴們有所幫助。

          本篇文章主要介紹網(wǎng)關(guān)跨域配置,網(wǎng)關(guān)過濾器編寫,網(wǎng)關(guān)的令牌桶算法限流【每秒10萬(wàn)QPS】

          首先我們來(lái)看什么是網(wǎng)關(guān)

          1.2 什么是微服務(wù)網(wǎng)關(guān)Gateway?

          This project provides a library for building an API Gateway on top of Spring WebFlux.

          gateway官網(wǎng):

          https://spring.io/projects/spring-cloud-gateway

          實(shí)現(xiàn)微服務(wù)網(wǎng)關(guān)的技術(shù)有很多,

          • nginx ?Nginx (engine x) 是一個(gè)高性能的HTTP和反向代理web服務(wù)器,同時(shí)也提供了IMAP/POP3/SMTP服務(wù)

          • zuul ,Zuul 是 Netflix 出品的一個(gè)基于 JVM 路由和服務(wù)端的負(fù)載均衡器。

          • spring-cloud-gateway, 是spring 出品的 基于spring 的網(wǎng)關(guān)項(xiàng)目,集成斷路器,路徑重寫,性能比Zuul好。

          我們使用gateway這個(gè)網(wǎng)關(guān)技術(shù),無(wú)縫銜接到基于spring cloud的微服務(wù)開發(fā)中來(lái)。

          1.3 微服務(wù)為什么要使用網(wǎng)關(guān)呢?

          不同的微服務(wù)一般會(huì)有不同的網(wǎng)絡(luò)地址,而外部客戶端可能需要調(diào)用多個(gè)服務(wù)的接口才能完成一個(gè)業(yè)務(wù)需求,如果讓客戶端直接與各個(gè)微服務(wù)通信,會(huì)有以下的問題:

          1. 客戶端會(huì)多次請(qǐng)求不同的微服務(wù),增加了客戶端的復(fù)雜性

          2. 存在跨域請(qǐng)求,在一定場(chǎng)景下處理相對(duì)復(fù)雜

          3. 認(rèn)證復(fù)雜,每個(gè)服務(wù)都需要獨(dú)立認(rèn)證

          4. 難以重構(gòu),隨著項(xiàng)目的迭代,可能需要重新劃分微服務(wù)。例如,可能將多個(gè)服務(wù)合并成一個(gè)或者將一個(gè)服務(wù)拆分成多個(gè)。如果客戶端直接與微服務(wù)通信,那么重構(gòu)將會(huì)很難實(shí)施

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

          以上這些問題可以借助網(wǎng)關(guān)解決。

          網(wǎng)關(guān)是介于客戶端和服務(wù)器端之間的中間層,所有的外部請(qǐng)求都會(huì)先經(jīng)過 網(wǎng)關(guān)這一層。也就是說(shuō),API 的實(shí)現(xiàn)方面更多的考慮業(yè)務(wù)邏輯,而安全、性能、監(jiān)控可以交由 網(wǎng)關(guān)來(lái)做,這樣既提高業(yè)務(wù)靈活性又不缺安全性,典型的架構(gòu)圖如圖所示:

          1.4 微服務(wù)網(wǎng)關(guān)優(yōu)點(diǎn)

          • 安全 ,只有網(wǎng)關(guān)系統(tǒng)對(duì)外進(jìn)行暴露,微服務(wù)可以隱藏在內(nèi)網(wǎng),通過防火墻保護(hù)。

          • 易于監(jiān)控??梢栽诰W(wǎng)關(guān)收集監(jiān)控?cái)?shù)據(jù)并將其推送到外部系統(tǒng)進(jìn)行分析。

          • 易于認(rèn)證??梢栽诰W(wǎng)關(guān)上進(jìn)行認(rèn)證,然后再將請(qǐng)求轉(zhuǎn)發(fā)到后端的微服務(wù),而無(wú)須在每個(gè)微服務(wù)中進(jìn)行認(rèn)證。

          • 減少了客戶端與各個(gè)微服務(wù)之間的交互次數(shù)

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

          1.5 總結(jié)

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

          二、微服務(wù)網(wǎng)關(guān)搭建及配置

          2.1 微服務(wù)網(wǎng)關(guān)微服務(wù)搭建

          由于我們開發(fā)的系統(tǒng) 有包括前臺(tái)系統(tǒng)和后臺(tái)系統(tǒng),后臺(tái)的系統(tǒng)給管理員使用。那么也需要調(diào)用各種微服務(wù),所以我們針對(duì)管理后臺(tái)搭建一個(gè)網(wǎng)關(guān)微服務(wù)。分析如下:

          搭建步驟:

          (1)依賴坐標(biāo)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)啟動(dòng)引導(dǎo)類: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

          參考官方手冊(cè):

          https://cloud.spring.io/spring-cloud-gateway/spring-cloud-gateway.html#_stripprefix_gatewayfilter_factory

          2.2 微服務(wù)網(wǎng)關(guān)跨域

          在啟動(dòng)類GatewayApplication中,加入跨域配置代碼如下

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

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

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

          三、微服務(wù)網(wǎng)關(guān)過濾器

          我們可以通過網(wǎng)關(guān)過濾器,實(shí)現(xiàn)一些邏輯的處理,比如ip黑白名單攔截、特定地址的攔截等。下面的代碼中做了兩個(gè)過濾器,并且設(shè)定的先后順序。

          (1)在網(wǎng)關(guān)微服務(wù)中創(chuàng)建IpFilter,無(wú)需配置其他,注冊(cè)到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?設(shè)置ip白名單
          ????????System.out.println("ip:"+remoteAddress.getHostName());
          ????????return?chain.filter(exchange);
          ????}
          ????@Override
          ????public?int?getOrder()?{
          ????????return?1;
          ????}
          }

          (2)在網(wǎng)關(guān)微服務(wù)中創(chuàng)建UrlFilter,無(wú)需配置其他,注冊(cè)到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;
          ????}
          }

          四、網(wǎng)關(guān)限流每秒10萬(wàn)請(qǐng)求

          我們之前說(shuō)過,網(wǎng)關(guān)可以做很多的事情,比如,限流,當(dāng)我們的系統(tǒng) 被頻繁的請(qǐng)求的時(shí)候,就有可能 將系統(tǒng)壓垮,所以 為了解決這個(gè)問題,需要在每一個(gè)微服務(wù)中做限流操作,但是如果有了網(wǎng)關(guān),那么就可以在網(wǎng)關(guān)系統(tǒng)做限流,因?yàn)樗械恼?qǐng)求都需要先通過網(wǎng)關(guān)系統(tǒng)才能路由到微服務(wù)中。

          4.1 限流實(shí)現(xiàn)思路分析

          看圖就完了,非常簡(jiǎn)單!

          4.2 令牌桶算法 介紹

          令牌桶算法是比較常見的限流算法之一,大概描述如下:

          1)所有的請(qǐng)求在處理之前都需要拿到一個(gè)可用的令牌才會(huì)被處理;

          2)根據(jù)限流大小,設(shè)置按照一定的速率往桶里添加令牌;

          3)桶設(shè)置最大的放置令牌限制,當(dāng)桶滿時(shí)、新添加的令牌就被丟棄或者拒絕;

          4)請(qǐng)求達(dá)到后首先要獲取令牌桶中的令牌,拿著令牌才可以進(jìn)行其他的業(yè)務(wù)邏輯,處理完業(yè)務(wù)邏輯之后,將令牌直接刪除;

          5)令牌桶有最低限額,當(dāng)桶中的令牌達(dá)到最低限額的時(shí)候,請(qǐng)求處理完之后將不會(huì)刪除令牌,以此保證足夠的限流

          如下圖:

          這個(gè)算法的實(shí)現(xiàn),有很多技術(shù),Guava(讀音: 瓜哇)是其中之一,redis客戶端也有其實(shí)現(xiàn)。歷史文章:200期階段匯總

          4.3 網(wǎng)關(guān)限流代碼實(shí)現(xiàn)

          需求:每個(gè)ip地址1秒內(nèi)只能發(fā)送10萬(wàn)請(qǐng)求,多出來(lái)的請(qǐng)求返回429錯(cuò)誤。

          代碼實(shí)現(xiàn):

          (1)spring cloud gateway 默認(rèn)使用redis的RateLimter限流算法來(lái)實(shí)現(xiàn)。所以我們要使用首先需要引入redis的依賴

          <dependency>
          ????<groupId>org.springframework.bootgroupId>
          ????<artifactId>spring-boot-starter-data-redis-reactiveartifactId>
          ????<version>2.1.3.RELEASEversion>
          dependency>
          (2)定義KeyResolver

          在GatewayApplicatioin引導(dǎo)類中添加如下代碼,KeyResolver用于計(jì)算某一個(gè)類型的限流的KEY也就是說(shuō),可以通過KeyResolver來(lái)指定限流的Key。

          ????//定義一個(gè)KeyResolver
          ????@Bean
          ????public?KeyResolver?ipKeyResolver()?{
          ????????return?new?KeyResolver()?{
          ????????????@Override
          ????????????public?Mono?resolve(ServerWebExchange?exchange)?{
          ????????????????return?Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
          ????????????}
          ????????};
          ????}
          (3)修改application.yml中配置項(xiàng),指定限制流量的配置以及REDIS的配置,修改后最終配置如下:
          spring:
          ??application:
          ????name:?apigateway
          ??cloud:
          ????gateway:
          ??????routes:
          ??????-?id:?open
          ????????uri:?lb://open
          ????????predicates:
          ????????-?Path=/open/**
          ????????filters:
          ????????-?StripPrefix=?1
          ????????-?name:?RequestRateLimiter?#請(qǐng)求數(shù)限流?名字不能隨便寫?
          ??????????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:令牌桶總?cè)萘俊?/p>

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

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

          通過在replenishRate和中設(shè)置相同的值來(lái)實(shí)現(xiàn)穩(wěn)定的速率burstCapacity。設(shè)置burstCapacity高于時(shí),可以允許臨時(shí)突發(fā)replenishRate。在這種情況下,需要在突發(fā)之間允許速率限制器一段時(shí)間(根據(jù)replenishRate),因?yàn)?次連續(xù)突發(fā)將導(dǎo)致請(qǐng)求被丟棄(HTTP 429 - Too Many Requests

          key-resolver: "#{@userKeyResolver}" 用于通過SPEL表達(dá)式來(lái)指定使用哪一個(gè)KeyResolver.

          如上配置:

          表示 一秒內(nèi),允許 一個(gè)請(qǐng)求通過,令牌桶的填充速率也是一秒鐘添加一個(gè)令牌。

          最大突發(fā)狀況 也只允許 一秒內(nèi)有一次請(qǐng)求,可以根據(jù)業(yè)務(wù)來(lái)調(diào)整 。

          (4)測(cè)試時(shí)需要注意服務(wù)啟動(dòng)順序,這里需要依賴于Redis,所以首先要啟動(dòng)redis
          • 啟動(dòng)redis

          • 啟動(dòng)注冊(cè)中心

          • 啟動(dòng)商品微服務(wù)

          • 啟動(dòng)gateway網(wǎng)關(guān)

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

          • 快速刷新,當(dāng)1秒內(nèi)發(fā)送超過10萬(wàn)次請(qǐng)求,就會(huì)返回429錯(cuò)誤。

          那么問題來(lái)了:怎么發(fā)送10萬(wàn)次請(qǐng)求呢? 知道的同學(xué),請(qǐng)?jiān)诹粞詤^(qū)評(píng)論。

          商城源碼下載



          商城管理后端演示圖



          源碼地址獲取方法,老規(guī)矩啦!

          識(shí)別下方二維碼,關(guān)注后回復(fù)【A107】

          即可獲取下載鏈接


          瀏覽 15
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  美国人A一级毛片 | 国产亚洲欧美精品久久久www | 91丨牛牛丨国产人妻 | 日韩一级a免费在线视频 | 国产性爱69 |