Spring Cloud Gateway限流實戰(zhàn)

歡迎訪問我的GitHub

https://github.com/zq2599/blog_demos

內(nèi)容:所有原創(chuàng)文章分類匯總及配套源碼,涉及Java抄腔、Docker绵患、Kubernetes藏雏、DevOPS等掘殴;

本篇概覽

  • 本文是《Spring Cloud Gateway實戰(zhàn)》系列的第八篇奏寨,經(jīng)過前面的學(xué)習(xí)病瞳,咱們對過濾器已了解得差不多悲酷,今天來補全過濾器的最后一個版塊:限流(RequestRateLimiter )

  • 默認的限流器是基于redis實現(xiàn)的设易,限流算法是大家熟悉的令牌桶(Token Bucket Algorithm),關(guān)于令牌捅的原理就不在此展開了顿肺,聰明的您看一眼下圖應(yīng)該就懂了:裝令牌的桶容量有限屠尊,例如最多20個讼昆,令牌進入桶的速度恒定(注意浸赫,這里是和漏桶算法的區(qū)別),例如每秒10個,底部每個請求能拿到令牌才會被處理:

在這里插入圖片描述

RequestRateLimiter基本套路

  • 使用RequestRateLimiter過濾器的步驟非常簡單:
  1. 準備可用的redis
  2. maven或者gradle中添加依賴<font color="blue">org.springframework.boot:spring-boot-starter-data-redis-reactive</font>
  3. 確定按照什么維度限流涧狮,例如按照請求中的username參數(shù)限流者冤,這是通過編寫KeyResolver接口的實現(xiàn)來完成的
  4. 配置application.yml文件涉枫,添加過濾器
  • 以上就是使用RequestRateLimiter過濾器的套路了愿汰,簡單么?接下來摇予,咱們先編碼再驗證

源碼下載

名稱 鏈接 備注
項目主頁 https://github.com/zq2599/blog_demos 該項目在GitHub上的主頁
git倉庫地址(https) https://github.com/zq2599/blog_demos.git 該項目源碼的倉庫地址酗宋,https協(xié)議
git倉庫地址(ssh) git@github.com:zq2599/blog_demos.git 該項目源碼的倉庫地址蜕猫,ssh協(xié)議
  • 這個git項目中有多個文件夾丹锹,本篇的源碼在<font color="blue">spring-cloud-tutorials</font>文件夾下芬失,如下圖紅框所示:
在這里插入圖片描述
  • <font color="blue">spring-cloud-tutorials</font>文件夾下有多個子工程租漂,本篇的代碼是<font color="red">gateway-requestratelimiter</font>哩治,如下圖紅框所示:
在這里插入圖片描述

準備工作

  • 為了更好的演示Gateway的效果业筏,在服務(wù)提供者<font color="blue">provider-hello</font>的代碼(Hello.java)中新增一個web接口蒜胖,可以接受一個入?yún)ⅲ?/li>
    @GetMapping("/userinfo")
    public String userInfo(@RequestParam("username") String username) {
        return Constants.HELLO_PREFIX + " " + username + ", " + dateStr();
    }
  • 后面的測試咱們就用上述接口台谢;

編碼

  • 在父工程<font color="blue">spring-cloud-tutorials</font>之下新增子工程<font color="red">gateway-requestratelimiter</font>,其pom.xml內(nèi)容如下蛇券,重點是<font color="blue">org.springframework.boot:spring-boot-starter-data-redis-reactive</font>:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-tutorials</artifactId>
        <groupId>com.bolingcavalry</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway-requestratelimiter</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.bolingcavalry</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
    </dependencies>
</project>
  • 配置文件application.yml,請注意RequestRateLimiter的幾個參數(shù)菜枷,已經(jīng)用中文添加了詳細的注釋:
server:
  #服務(wù)端口
  port: 8081
spring:
  application:
    name: circuitbreaker-gateway
  # redis配置
  redis:
    host: 192.168.50.43
    port: 6379

  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - name: RequestRateLimiter
              args:
                # 令牌入桶的速度為每秒100個啤誊,相當(dāng)于QPS
                redis-rate-limiter.replenishRate: 100
                # 桶內(nèi)能裝200個令牌蚊锹,相當(dāng)于峰值稚瘾,要注意的是:第一秒從桶內(nèi)能去200個摊欠,但是第二秒只能取到100個了些椒,因為入桶速度是每秒100個
                redis-rate-limiter.burstCapacity: 200
                # 每個請求需要的令牌數(shù)
                redis-rate-limiter.requestedTokens: 1
  • 指定限流維度的代碼CustomizeConfig.java,這里是根據(jù)請求參數(shù)<font color="blue">username</font>的值來限流的免糕,假設(shè)真實請求中一半請求的username的等于<font color="red">Tom</font>牌芋,另一半的username的等于<font color="red">Jerry</font>松逊,按照application.yml的配置经宏,Tom的請求QPS為10,Jerry的QPS也是10:
package com.bolingcavalry.gateway.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
import java.util.Objects;

@Configuration
public class CustomizeConfig {
    @Bean
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("username"));
    }
}
  • 毫無營養(yǎng)的啟動類RequestRateLimiterApplication.java:
package com.bolingcavalry.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RequestRateLimiterApplication {
    public static void main(String[] args) {
        SpringApplication.run(RequestRateLimiterApplication.class,args);
    }
}
  • 代碼寫完了,接下來開始驗證苹熏;

驗證(桶容量等于入桶速度)

  • 首先驗證的是桶容量等于入桶速度時的效果轨域,請修改<font color="blue">gateway-requestratelimiter</font>應(yīng)用的application.yml中文件杀餐,使得redis-rate-limiter.replenishRate和redis-rate-limiter.burstCapacity的值都等于100枉长,也就是說桶的大小等于100必峰,每秒放入的令牌數(shù)也是100

  • 確保redis已經(jīng)啟動钻蹬,并且與application.yml中的配置保持一直

  • 啟動nacos(provider-hello依賴)

  • 啟動服務(wù)提供者<font color="blue">provider-hello</font>

  • 啟動<font color="blue">gateway-requestratelimiter</font>

  • 為了模擬web請求肝匆,我這里使用了<font color="blue">Apache Benchmark</font>旗国,windows版本的下載地址:
    https://www.apachelounge.com/download/VS16/binaries/httpd-2.4.48-win64-VS16.zip

  • 上述文件下載解壓后即可使用滚澜,在控制臺進入<font color="blue">Apache24\bin</font>后執(zhí)行以下命令设捐,意思是向指定地址發(fā)送10000個請求萝招,并發(fā)數(shù)為2:

ab -n 10000  -c 2 http://localhost:8081/hello/userinfo?username=Tom
  • 控制臺輸出如下槐沼,可見不到八秒的時間捌治,只成功了800個肖油,證明限流符合預(yù)期:
在這里插入圖片描述

驗證(桶容量大于入桶速度)

  • 接下來試試桶容量大于入桶速度時的限流效果森枪,這對于我們控制峰值響應(yīng)有很重要的參考價值

  • 請修改<font color="blue">gateway-requestratelimiter</font>應(yīng)用的application.yml中文件,redis-rate-limiter.replenishRate維持<font color="blue">100</font>不變式散,但是redis-rate-limiter.burstCapacity改成<font color="red">200</font>暴拄,也就是說每秒放入的令牌數(shù)還是100揍移,但桶的容量翻倍了

  • 重啟應(yīng)用<font color="blue">gateway-requestratelimiter</font>

  • 再次執(zhí)行以下命令反肋,意思是向指定地址發(fā)送10000個請求石蔗,并發(fā)數(shù)為2:

ab -n 10000  -c 2 http://localhost:8081/hello/userinfo?username=Tom
  • 測試結(jié)果如下圖罕邀,可見符合預(yù)期,可以將桶內(nèi)令牌全部用掉养距,以支撐峰值超過QPS的場景:
在這里插入圖片描述

驗證(根據(jù)username的維度限流)

  • 接下來驗證限流的維度诉探,究竟是不是按照請求參數(shù)username的值來限流的

  • 咱們打開兩個命令行,同時發(fā)送請求(動作要快)棍厌,第一個的username等于<font color="blue">Tom</font>肾胯,第二個等于<font color="blue">Jerry</font>,理論上推測耘纱,如果都是8秒內(nèi)完成敬肚,那么每個命令都有900個請求能成功

  • 測試結(jié)果如下圖,可見符合預(yù)期束析,每個username用的是自己的令牌:

在這里插入圖片描述
  • 至此,Spring Cloud Gateway限流實戰(zhàn)已經(jīng)完成第美,如此簡單易用的限流方案,希望能給您的學(xué)習(xí)和使用帶來參考

你不孤單,欣宸原創(chuàng)一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 數(shù)據(jù)庫+中間件系列
  6. DevOps系列

歡迎關(guān)注公眾號:程序員欣宸

微信搜索「程序員欣宸」仔拟,我是欣宸载佳,期待與您一同暢游Java世界...
https://github.com/zq2599/blog_demos

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末姑躲,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機焊虏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人敌呈,你說我怎么就攤上這事。” “怎么了姊舵?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵尖昏,是天一觀的道長。 經(jīng)常有香客問我,道長纹份,這世上最難降的妖魔是什么牍疏? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮享怀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己搓幌,他們只是感情好鼻种,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著圃泡,像睡著了一般鳖目。 火紅的嫁衣襯著肌膚如雪抢韭。 梳的紋絲不亂的頭發(fā)上交洗,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機與錄音建瘫,去河邊找鬼晾咪。 笑死,一個胖子當(dāng)著我的面吹牛昼蛀,可吹牛的內(nèi)容都是我干的叼旋。 我是一名探鬼主播讹剔,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼为居!你這毒婦竟也來了劫狠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤苔埋,失蹤者是張志新(化名)和其女友劉穎懦砂,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體组橄,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡荞膘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了玉工。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羽资。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖遵班,靈堂內(nèi)的尸體忽然破棺而出屠升,到底是詐尸還是另有隱情瞄勾,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響癣丧,放射性物質(zhì)發(fā)生泄漏闹丐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦糙麦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宝与,卻和暖如春焚廊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背习劫。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工咆瘟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诽里。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓袒餐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谤狡。 傳聞我的和親對象是個殘疾皇子灸眼,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容