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

Spring Boot使用Redisson實(shí)現(xiàn)滑動窗口限流的項(xiàng)目實(shí)踐

 更新時(shí)間:2024年03月03日 10:59:24   作者:冥胖胖9  
滑動窗口限流是一種流量控制策略,用于控制在一定時(shí)間內(nèi)的請求頻率,本文主要介紹了Spring Boot使用Redisson實(shí)現(xiàn)滑動窗口限流的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下

一、背景

在一些業(yè)務(wù)場景中,我們可能會提供一些API接口來給用戶使用,這些接口是不需要認(rèn)證的。比如:忘記密碼,重置密碼的接口,這些接口用戶可以隨意調(diào)用。為了防止這些接口被攻擊者惡意頻繁調(diào)用,消耗我們的系統(tǒng)資源,通常我們會對這些接口做限流保護(hù),否則可能會導(dǎo)致我們的服務(wù)器的宕機(jī)。

其實(shí)限流可以認(rèn)為是服務(wù)降級的一種,限流通過限制請求的流量以達(dá)到保護(hù)系統(tǒng)的目的。今天我們一起來討論一下在Redis緩存中怎么通過Redisson實(shí)現(xiàn)滑動窗口限流。

二、滑動窗口限流算法

1. 原理

我們先來了解一下滑動窗口限流的實(shí)現(xiàn)原理,話不多說,先上圖。

從上圖我們可以得知,有一個(gè)時(shí)間窗口隨著時(shí)間軸在向右移動,我們可以記錄這個(gè)時(shí)間窗口內(nèi)的請求次數(shù),當(dāng)超過我們允許的閾值時(shí),則進(jìn)行限流不能繼續(xù)進(jìn)行請求。

2. 具體實(shí)現(xiàn)步驟

主要實(shí)現(xiàn)步驟如下:

  • 我們需要定義一個(gè)時(shí)間窗口,例如窗口大小為1分鐘。
  • 每次有請求時(shí),使用redis中的zset將這條請求記錄下來。                                                     充分利用zset這個(gè)數(shù)據(jù)結(jié)果的特點(diǎn),zet一條記錄由兩個(gè)成員(score和member)來表示,并且會按照score進(jìn)行排序。方便我們后面進(jìn)行刪除滑動后窗口之前的請求記錄,和統(tǒng)計(jì)當(dāng)前窗口內(nèi)請求總數(shù)。
  • 通過ZREMRANGEBYSCORE命令,刪除zset中當(dāng)前窗口之前的請求記錄。
  • 通過ZCARD命令,統(tǒng)計(jì)當(dāng)前窗口內(nèi)的請求數(shù)量。

所以,我們使用滑動窗口的思想是,只保留當(dāng)前時(shí)間窗口類的請求記錄,而丟棄當(dāng)前窗口之外的記錄。當(dāng)下次有請求進(jìn)來時(shí),我們只需要判斷當(dāng)前窗口內(nèi)的請求是否超過閾值就可以了。未超過則放行,超過則限流。

3. 偽代碼

根據(jù)以上步驟我們寫了一段偽代碼,如果考慮并發(fā)場景則需要考慮使用Lua腳本。

   public boolean allowRequest(String requestKey) {
        // 定義一個(gè)時(shí)間窗口為1分鐘
        long windowSize = Duration.ofMinutes(1).toSeconds();

        // 定義時(shí)間窗口內(nèi)請求閾值為100
        long limit = 100;

        // 當(dāng)前時(shí)間戳
        long currentTime = System.currentTimeMillis();

        // 窗口開始時(shí)間為當(dāng)前時(shí)間戳 - 窗口大小
        long windowStart = currentTime - windowSize * 1000;

        // 刪除當(dāng)前窗口開始之前的所有數(shù)據(jù)
        Jedis.zremrangeByScore(requestKey, "0", String.valueOf(windowStart));

        // 計(jì)算當(dāng)前窗口內(nèi)的請求總數(shù)
        long count = Jedis.zcard(requestKey);

        if (count < limit) {
            // 如果允許訪問,則將當(dāng)前請求加到窗口內(nèi)
            Jedis.zadd(requestKey, currentTime, String.valueOf(currentTime));
            return true;
        }
        return false;
    }
}

三、怎么使用Redisson進(jìn)行滑動窗口限流

在redisson中已經(jīng)為我們實(shí)現(xiàn)好了滑動窗口限流,通過redissonClient拿到限流器后,配置好時(shí)間窗口和限流速率就能直接使用了。實(shí)現(xiàn)原理和上面我們的偽代碼是一樣的,只是它將這一部分封裝好了,我們拿到后開箱即用。直接上代碼:

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.filter.OncePerRequestFilter;

public class RateLimiterFilter extends OncePerRequestFilter {

    private final Logger log = LoggerFactory.getLogger(RateLimiterFilter.class);

    private static final String RATE_LIMIT_KEY = "rateLimit:yourApiKey";
    private static final int MAX_REQUESTS_PER_MINUTE = 10;

    private final RedissonClient redissonClient;

    public RateLimiterFilter(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(RATE_LIMIT_KEY);
        // rateLimiter.trySetRate就是設(shè)置限流參數(shù),RateType有兩種,OVERALL是全局限流 ,PER_CLIENT是單Client限流(可以認(rèn)為就是單機(jī)限流),這里我們只討論全局模式。
        // 而后面三個(gè)參數(shù)的作用就是設(shè)置在多長時(shí)間窗口內(nèi)(rateInterval+IntervalUnit),許可總量不超過多少(rate)
        // 上面代碼中我設(shè)置的值就是1分鐘內(nèi)總許可數(shù)不超過10個(gè)
        rateLimiter.trySetRate(RateType.OVERALL, MAX_REQUESTS_PER_MINUTE, 1, RateIntervalUnit.MINUTES);
        // 調(diào)用rateLimiter的tryAcquire()或者acquire()方法即可獲取許可
        if (!rateLimiter.tryAcquire()) {
            
            String path = request.getRequestURI().substring(request.getContextPath().length());
            log.error("當(dāng)前請求觸發(fā)限流策略,請求: {} 已經(jīng)被限流.", path);

            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.getWriter().write("Too many requests!");
            return;
        }
        filterChain.doFilter(request, response);
    }
}

四、滑動窗口限流的優(yōu)勢

滑動窗口限流是一種流量控制策略,用于控制在一定時(shí)間內(nèi)的請求頻率。它的主要優(yōu)點(diǎn)是可以在單位時(shí)間內(nèi)平滑的控制流量,而不是簡單的設(shè)置固定的請求數(shù)或速率。這使得系統(tǒng)可以更靈活的應(yīng)對突發(fā)流量或峰值流量,而不會因?yàn)楣潭ㄋ俾实南拗贫速M(fèi)或降低系統(tǒng)性能。

這種限流算法可以在分布式系統(tǒng)、API服務(wù)等各種場景中使用,以確保系統(tǒng)的穩(wěn)定性和可用性,防止過多的請求或惡意請求對系統(tǒng)造成負(fù)擔(dān)或崩潰。

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

相關(guān)文章

  • Java實(shí)現(xiàn)轉(zhuǎn)換圖片格式的示例代碼

    Java實(shí)現(xiàn)轉(zhuǎn)換圖片格式的示例代碼

    在日常的軟件開發(fā)中,處理圖像文件是一項(xiàng)常見任務(wù),這篇文章將實(shí)現(xiàn)實(shí)現(xiàn)一個(gè)簡單的Java程序,用于將一種圖片格式轉(zhuǎn)換為另一種格式,需要的可以了解下
    2025-02-02
  • java后臺實(shí)現(xiàn)支付寶對賬功能的示例代碼

    java后臺實(shí)現(xiàn)支付寶對賬功能的示例代碼

    這篇文章主要介紹了java后臺實(shí)現(xiàn)支付寶對賬功能的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • mybatis+springboot中使用mysql的實(shí)例

    mybatis+springboot中使用mysql的實(shí)例

    在軟件開發(fā)中,數(shù)據(jù)庫的引入是必不可少的,這里來展現(xiàn)一下通過mybatis框架在springboot中使用mysql,具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-07-07
  • Spring MVC 請求參數(shù)處理全解析

    Spring MVC 請求參數(shù)處理全解析

    本文主要介紹了Spring框架中處理HTTP請求參數(shù)的方法,包括傳遞單個(gè)參數(shù)、多個(gè)參數(shù)、對象參數(shù)、數(shù)組、集合、JSON數(shù)據(jù)、路徑變量、上傳文件、Cookie和Session的獲取以及Header的獲取,感興趣的朋友一起看看吧
    2025-12-12
  • Java實(shí)現(xiàn)的百度語音識別功能示例

    Java實(shí)現(xiàn)的百度語音識別功能示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的百度語音識別功能,較為簡明扼要的分析了Java調(diào)用百度語音接口相關(guān)操作步驟,并給出了具體的語音識別用法代碼示例,需要的朋友可以參考下
    2018-08-08
  • Java數(shù)組擴(kuò)容實(shí)例代碼

    Java數(shù)組擴(kuò)容實(shí)例代碼

    這篇文章主要介紹了Java數(shù)組擴(kuò)容實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2017-11-11
  • java實(shí)現(xiàn)圖書管理系統(tǒng)

    java實(shí)現(xiàn)圖書管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • Java流程控制break和continue

    Java流程控制break和continue

    這篇文章主要介紹了Java流程控制break和continue,下面文章圍繞break和continue的相關(guān)資料展開詳細(xì)內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2021-12-12
  • 深入剖析構(gòu)建JSON字符串的三種方式(推薦)

    深入剖析構(gòu)建JSON字符串的三種方式(推薦)

    下面小編就為大家?guī)硪黄钊肫饰鰳?gòu)建JSON字符串的三種方式(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • SpringBoot中JPA實(shí)現(xiàn)Sort排序的三種方式小結(jié)

    SpringBoot中JPA實(shí)現(xiàn)Sort排序的三種方式小結(jié)

    這篇文章主要介紹了SpringBoot中JPA實(shí)現(xiàn)Sort排序的三種方式小結(jié),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評論

吉林省| 乐都县| 塔城市| 陵水| 景泰县| 安徽省| 灯塔市| 台湾省| 镇沅| 张家界市| 昂仁县| 丽江市| 武川县| 攀枝花市| 商南县| 印江| 铁岭县| 新民市| 四会市| 丰都县| 屏东市| 阳信县| 五莲县| 浦县| 襄樊市| 方正县| 怀宁县| 北宁市| 吉木萨尔县| 博客| 安泽县| 华亭县| 巫山县| 柳林县| 象州县| 溧阳市| 乐山市| 玉环县| 江永县| 华阴市| 蛟河市|