最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)API接口限流

 更新時(shí)間:2025年08月07日 09:52:12   作者:星辰聊技術(shù)  
訪問(wèn)速率限制是一種API訪問(wèn)限制的策略,它限制客戶端在一定時(shí)間內(nèi)調(diào)用API的次數(shù),本文就來(lái)介紹一下Spring Boot中使用Bucket4j實(shí)現(xiàn)限流,感興趣的可以了解一下

1. 簡(jiǎn)介

訪問(wèn)速率限制是一種API訪問(wèn)限制的策略。它限制客戶端在一定時(shí)間內(nèi)調(diào)用 API 的次數(shù)。這有助于保護(hù)應(yīng)用程序接口,防止無(wú)意或惡意的過(guò)度使用。

速率限制通常是通過(guò)跟蹤 IP 地址或更具體的業(yè)務(wù)方式(如 API 密鑰或訪問(wèn)令牌等方式)來(lái)應(yīng)用于 API 的。作為 API 開發(fā)人員,當(dāng)客戶端達(dá)到限制時(shí),我們有幾種選擇:

  • 請(qǐng)求排隊(duì),直到剩余時(shí)間結(jié)束(這也是最常用的方式)
  • 拒絕請(qǐng)求(HTTP 429 請(qǐng)求過(guò)多)

本篇文章將介紹一款開源的組件Bucket4j,該組件提供了強(qiáng)大的限流功能。基于基于令牌桶算法。既可用于獨(dú)立的 JVM 應(yīng)用程序,也可用于集群環(huán)境。它還通過(guò) JCache(JSR107)規(guī)范支持內(nèi)存或分布式緩存。

令牌桶算法

假設(shè)我們有一個(gè) "桶",其容量被定義為可容納的令牌數(shù)量。每當(dāng)消費(fèi)者想要訪問(wèn) API 端點(diǎn)時(shí),就必須從桶中獲取一個(gè)令牌。如果有令牌,我們就會(huì)從數(shù)據(jù)桶中移除令牌,并接受請(qǐng)求。反之,如果程序桶中沒(méi)有令牌,我們就會(huì)拒絕請(qǐng)求。

在請(qǐng)求消耗令牌(token)的同時(shí),我們也在以某種固定的速度補(bǔ)充令牌。

考慮一個(gè)速率限制為每分鐘 100 個(gè)請(qǐng)求的應(yīng)用程序接口。我們可以創(chuàng)建一個(gè)容量為 100 的水桶,每分鐘填充 100 個(gè)令牌。如果我們?cè)谝环昼妰?nèi)收到 70 個(gè)請(qǐng)求,少于可用令牌的數(shù)量,那么在下一分鐘開始時(shí),我們只需再添加 30 個(gè)令牌,就能使水桶達(dá)到容量。另一方面,如果我們?cè)?40 秒內(nèi)用完了所有令牌,我們將等待 20 秒來(lái)重新裝滿令牌桶。

接下來(lái)將詳細(xì)介紹在Spring Boot中如何使用Bucket4j實(shí)現(xiàn)限流。

2. 實(shí)戰(zhàn)案例

2.1 環(huán)境準(zhǔn)備

引入依賴

<dependency>
  <groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
  <artifactId>bucket4j-spring-boot-starter</artifactId>
  <version>0.12.7</version>
</dependency>
<dependency>
  <groupId>com.bucket4j</groupId>
  <artifactId>bucket4j-redis</artifactId>
  <version>8.10.1</version>
</dependency>
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
</dependency>
<dependency>
  <groupId>io.micrometer</groupId>
  <artifactId>micrometer-core</artifactId>
</dependency>
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.

接下來(lái)的案例是基于redis的,所以引入了jedis。你也可以是lettuce或者是redisson但是這2個(gè)貌似需要是webflux環(huán)境。

jedis配置

@Bean
public JedisPool jedisPool(
    @Value("${spring.data.redis.port}") Integer port,
    @Value("${spring.data.redis.host}") String host,
    @Value("${spring.data.redis.password}") String password,
    @Value("${spring.data.redis.database}") Integer database
  ) {
  // buildPoolConfig方法自己進(jìn)行配置吧
  final JedisPoolConfig poolConfig = buildPoolConfig();
  return new JedisPool(poolConfig, host, port, 60000, password, database);
}
1.2.3.4.5.6.7.8.9.10.11.

以上基礎(chǔ)環(huán)境就準(zhǔn)備好了,接下來(lái)就可以進(jìn)行規(guī)則配置。而規(guī)則的配置可以基于2中方式,基于配置文件和基于注解(AOP)。

定義接口

@RestController
@RequestMapping("/products")
public class ProductController {


  @GetMapping("/{id}")
  public Product getProduct(@PathVariable Integer id) {
    return new Product(id, "商品 - " + id, BigDecimal.valueOf(new Random().nextDouble(1000))) ;
  }
}
1.2.3.4.5.6.7.8.9.10.

接下來(lái)我將基于上面的接口進(jìn)行限流的配置。

2.2 基于配置文件

基于配置文件的規(guī)則配置底層實(shí)現(xiàn)是通過(guò)Filter。

bucket4j:
  cache-to-use: redis-jedis
  filter-config-caching-enabled: true
  filters:
  - cache-name: product_cache_name
    id: product_filter
    # 配置請(qǐng)求url的規(guī)則;這里底層是通過(guò)正則表達(dá)式進(jìn)行匹配的
    url: /products/.*
    rate-limits:
    - 
      #這里的cache-key非常關(guān)鍵;用于區(qū)分不同請(qǐng)求的情況;
      #比如,這里我會(huì)根據(jù)不同的請(qǐng)求id來(lái)現(xiàn)在訪問(wèn)速率
      #這里可以寫spel表達(dá)式,這里調(diào)用的是HttpServletRequest#getParameter方法
      cache-key: getParameter("id")
      bandwidths:
      #配置桶的容量
      - capacity: 2
        # 時(shí)間
        time: 30
        # 單位
        unit: seconds
        # 填充速度;這會(huì)每隔30秒進(jìn)行填充
        refill-speed: interval
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.

修改默認(rèn)的限流提示

bucket4j:
  filters:
  - cache-name: product_cache_name
    http-content-type: 'application/json;charset=utf-8'
    http-response-body: '{"code": -1, "message": "請(qǐng)求太快了"}'
1.2.3.4.5.

注意:你必須同時(shí)要設(shè)置content-type設(shè)置字符編碼,否則會(huì)亂碼。

條件放行

你也可以通過(guò)如下屬性進(jìn)行有條件的放行;

bucket4j:
  filters:
  - cache-name: product_cache_name
    rate-limits:
    - 
      skip-condition: 'getParameter("id").equals("6")'
1.2.3.4.5.6.

當(dāng)請(qǐng)求id的值為6時(shí)則跳過(guò)規(guī)則,直接方向。

以上是基于配置文件規(guī)則的應(yīng)用,它還有很多其它的配置屬性,詳細(xì)查看官方文檔

https://github.com/MarcGiffing/bucket4j-spring-boot-starter

接下來(lái)介紹基于注解的方式。

2.3 基于注解

通過(guò)"@RateLimiting"注解,AOP 可以攔截目標(biāo)方法。這樣,你就可以全面訪問(wèn)方法參數(shù),輕松定義速率限制鍵或有條件地跳過(guò)速率限制。

配置文件中配置規(guī)則

bucket4j:
  methods:
  - name: storage_rate #在代碼中會(huì)通過(guò)該名稱引用
    cache-name: storage_cache_name
    rate-limit:
      bandwidths:
      - capacity: 2
        time: 30
        unit: seconds
        refill-speed: interval
1.2.3.4.5.6.7.8.9.10.

接口注解,配置限流

@RateLimiting(
    name = "storage_rate", 
    cacheKey = "'storage-' + #id",
    skipCondition = "#name eq 'admin'",
    ratePerMethod = true,
    fallbackMethodName = "getStorageFallback"
  )
@GetMapping("/{id}")
public R<Storage> getStorage(@PathVariable Integer id, String name) {
  return R.success(new Storage(id, "SP001 - " + id, new Random().nextInt(10000))) ;
}
// 回退方法的簽名必須與業(yè)務(wù)方法一致
public R<Storage> getStorageFallback(Integer id, String name) {
  return R.failure(String.format("請(qǐng)求id=%d,name=%s被限流", id, name)) ;
}
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

skipCondition:該屬性定義了如果請(qǐng)求的name的值為admin則跳過(guò),不限流。

@RateLimiting注解還可以應(yīng)用到類中,這樣該類中的所有方法都會(huì)被限流,如下示例:

@Service
@RateLimiting(
    name = "storage_rate", 
    cacheKey = "getName",
    ratePerMethod = false
  )
public class StorageService {


  public Storage queryStorageById(Integer id) {
    return new Storage(id, "SP001 - " + id, new Random().nextInt(10000)) ;
  }
  
  @IgnoreRateLimiting
  public List<Storage> queryStorages() {
    return List.of(
        new Storage(1, "SP001 - " + 1, new Random().nextInt(10000)),
        new Storage(2, "SP002 - " + 2, new Random().nextInt(10000)),
        new Storage(3, "SP003 - " + 3, new Random().nextInt(10000))
      ) ;
  }
}
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.

上面代碼queryStorageById會(huì)被限流,而queryStorages方法被@IgnoreRateLimiting注解標(biāo)準(zhǔn),所以不會(huì)被限流。

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)API接口限流的文章就介紹到這了,更多相關(guān)SpringBoot API接口限流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java語(yǔ)言通過(guò)三種方法實(shí)現(xiàn)隊(duì)列的示例代碼

    Java語(yǔ)言通過(guò)三種方法實(shí)現(xiàn)隊(duì)列的示例代碼

    這篇文章主要介紹了Java語(yǔ)言通過(guò)三種方法來(lái)實(shí)現(xiàn)隊(duì)列的實(shí)例代碼,數(shù)組模擬隊(duì)列,通過(guò)對(duì)定義的了解,發(fā)現(xiàn)隊(duì)列很像我們的數(shù)組,下面我們通過(guò)實(shí)踐給大家詳細(xì)介紹,需要的朋友可以參考下
    2022-02-02
  • java 如何將圖片按照原尺寸比例存入word中

    java 如何將圖片按照原尺寸比例存入word中

    這篇文章主要介紹了java 如何將圖片按照原尺寸比例存入word中的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java面試崗常見問(wèn)題之ArrayList和LinkedList的區(qū)別

    Java面試崗常見問(wèn)題之ArrayList和LinkedList的區(qū)別

    ArrayList和LinkedList作為我們Java中最常使用的集合類,很多人在被問(wèn)到他們的區(qū)別時(shí),憋了半天僅僅冒出一句:一個(gè)是數(shù)組一個(gè)是鏈表。這樣回答簡(jiǎn)直讓面試官吐血。為了讓兄弟們打好基礎(chǔ),我們通過(guò)實(shí)際的使用測(cè)試,好好說(shuō)一下ArrayList和LinkedList的區(qū)別這道經(jīng)典的面試題
    2022-01-01
  • 關(guān)于idea無(wú)法修改模板中jdk版本問(wèn)題

    關(guān)于idea無(wú)法修改模板中jdk版本問(wèn)題

    這篇文章主要介紹了關(guān)于idea無(wú)法修改模板中jdk版本問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • SpringMVC之@requestBody的作用及說(shuō)明

    SpringMVC之@requestBody的作用及說(shuō)明

    這篇文章主要介紹了SpringMVC之@requestBody的作用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java中List for循環(huán)的6種寫法總結(jié)(推薦)

    Java中List for循環(huán)的6種寫法總結(jié)(推薦)

    下面小編就為大家?guī)?lái)一篇Java中List for循環(huán)的6種寫法總結(jié)(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • 詳解Java在redis中進(jìn)行對(duì)象的緩存

    詳解Java在redis中進(jìn)行對(duì)象的緩存

    這篇文章主要介紹了Java在redis中進(jìn)行對(duì)象的緩存,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 你一定不知道的Java Unsafe用法詳解

    你一定不知道的Java Unsafe用法詳解

    Unsafe是位于sun.misc包下的一個(gè)類,主要提供一些用于執(zhí)行低級(jí)別、不安全操作的方法,如直接訪問(wèn)系統(tǒng)內(nèi)存資源、自主管理內(nèi)存資源等,下面這篇文章主要給大家介紹了關(guān)于Java Unsafe用法的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • Java使用Apache Commons高效處理CSV文件的操作指南

    Java使用Apache Commons高效處理CSV文件的操作指南

    在 Java 開發(fā)中,CSV(Comma-Separated Values,逗號(hào)分隔值)是一種常見的數(shù)據(jù)存儲(chǔ)格式,廣泛用于數(shù)據(jù)交換和簡(jiǎn)單的存儲(chǔ)任務(wù),本文將介紹Java使用Apache Commons高效處理CSV文件的操作指南,需要的朋友可以參考下
    2025-03-03
  • java中利用棧實(shí)現(xiàn)字符串回文算法

    java中利用棧實(shí)現(xiàn)字符串回文算法

    給定一個(gè)由多個(gè)a和b組成的字符串?dāng)?shù)組,字符串中有一個(gè)特殊的字符X,位于字符串的正中間,例如(aaaabbbbXabaabbbb),如何判定該字符串是否回文
    2020-12-12

最新評(píng)論

繁峙县| 海晏县| 庆城县| 中方县| 镇雄县| 道孚县| 仁化县| 崇义县| 大港区| 龙岩市| 银川市| 延安市| 准格尔旗| 阿勒泰市| 五河县| 漳浦县| 都江堰市| 临西县| 安仁县| 本溪市| 修水县| 景洪市| 北京市| 广河县| 阳高县| 图木舒克市| 马边| 敖汉旗| 花莲市| 临颍县| 高州市| 本溪市| 天峨县| 清镇市| 襄垣县| 广饶县| 武山县| 正安县| 家居| 阳谷县| 基隆市|