国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter)

這篇具有很好參考價(jià)值的文章主要介紹了【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1. 什么是限流

限流就是在用戶訪問(wèn)次數(shù)龐大時(shí),對(duì)系統(tǒng)資源的一種保護(hù)手段。高峰期,用戶可能對(duì)某個(gè)接口的訪問(wèn)頻率急劇升高,后端接口通常需要進(jìn)行DB操作,接口訪問(wèn)頻率升高,DB的IO次數(shù)就顯著增高,從而極大的影響整個(gè)系統(tǒng)的性能。如果不對(duì)用戶訪問(wèn)頻率進(jìn)行限制,高頻的訪問(wèn)容易打跨整個(gè)服務(wù)

2. 常見的限流策略

2.1 漏斗算法

我們想象一個(gè)漏斗,大口用于接收客戶端的請(qǐng)求,小口用于流出用戶的請(qǐng)求。漏斗能夠保證流出請(qǐng)求數(shù)量的穩(wěn)定。

【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter),前后端的那些事,spring boot,限流,RateLimiter,令牌桶算法,漏斗算法

2.2 令牌桶算法

令牌桶算法,每個(gè)請(qǐng)求想要通過(guò),就必須從令牌桶中取出一個(gè)令牌。否則無(wú)法通過(guò)。而令牌會(huì)內(nèi)部會(huì)維護(hù)每秒鐘產(chǎn)生的令牌的數(shù)量,使得每秒鐘能夠通過(guò)的請(qǐng)求數(shù)量得到控制

【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter),前后端的那些事,spring boot,限流,RateLimiter,令牌桶算法,漏斗算法

2.3 次數(shù)統(tǒng)計(jì)

次數(shù)統(tǒng)計(jì)的方式非常直接,每一次請(qǐng)求都進(jìn)行計(jì)數(shù),并統(tǒng)計(jì)時(shí)間戳。如果下一次請(qǐng)求攜帶的時(shí)間戳在一定的頻率內(nèi),進(jìn)行次數(shù)的累加。如果次數(shù)達(dá)到一定閾值,則拒絕后續(xù)請(qǐng)求。直到下一次請(qǐng)求時(shí)間戳大于初始時(shí)間戳,重置接口次數(shù)與時(shí)間戳

【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter),前后端的那些事,spring boot,限流,RateLimiter,令牌桶算法,漏斗算法

3. 令牌桶代碼編寫

令牌桶算法我們可以使用Google guava包下的封裝好的RateLimiter,緊緊抱住大爹大腿

另外,ip頻率限制是一個(gè)橫向邏輯,該功能應(yīng)該保護(hù)所有后端接口,因此我們可以采用Spring AOP增強(qiáng)所有后端接口

另外,我們需要對(duì)同一個(gè)用戶,對(duì)同一個(gè)接口訪問(wèn)次數(shù)進(jìn)行限流,這意味著我們需要限制的是——(用戶,接口)這樣的一對(duì)元組。用戶可以通過(guò)ip進(jìn)行限定,也就是說(shuō),后端是同一個(gè)ip針對(duì)同一個(gè)請(qǐng)求的訪問(wèn)進(jìn)行限流

因此我們需要為每一個(gè)這樣的(ip,method)使用令牌桶限流,(ip,method)-> RateLimiter。ip + method這一對(duì)元組唯一確定一個(gè)RateLimiter

我們可以采用Map緩存這樣的一一對(duì)應(yīng)的關(guān)系

But,HashMap顯然不適合,應(yīng)為HashMap不防并發(fā);另外ConcurrentHashMap也不合適,假如一個(gè)用戶發(fā)出一個(gè)請(qǐng)求后就下線了,那么這個(gè)key就會(huì)長(zhǎng)久的存活于內(nèi)存中,這極大的增加了內(nèi)存的壓力

因此我們采用Google的Cache

Google大爹提供的Cache功能極其強(qiáng)大,讀者可以自行閱讀下面文檔

/**
 * A builder of {@link LoadingCache} and {@link Cache} instances having any combination of the
 * following features:
 *
 * <ul>
 *   <li>automatic loading of entries into the cache
 *   <li>least-recently-used eviction when a maximum size is exceeded
 *   <li>time-based expiration of entries, measured since last access or last write
 *   <li>keys automatically wrapped in {@code WeakReference}
 *   <li>values automatically wrapped in {@code WeakReference} or {@code SoftReference}
 *   <li>notification of evicted (or otherwise removed) entries
 *   <li>accumulation of cache access statistics
 * </ul>
 * /

IpLimiterAspect.java

import com.fgbg.demo.utils.RequestUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * 限制每個(gè)ip對(duì)同一個(gè)接口的訪問(wèn)頻率
 */
@Component
@Aspect
@Slf4j
@RestController
public class IpLimiterAspect {
    @Autowired
    private RequestUtils requestUtils;

    // 每秒生成1個(gè)令牌, 同個(gè)ip訪問(wèn)同個(gè)接口的QPS為1
    private final double PERMIT_PER_SECOND = 1;

    // 創(chuàng)建本地緩存
    private final Cache<String, RateLimiter> limiterCache = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build();

    @Around("execution(* com.fgbg.demo.controller..*.*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        // 構(gòu)造key
        Signature signature = proceedingJoinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        String methodName = proceedingJoinPoint.getTarget().getClass().getName() + "." + methodSignature.getName();
        String key = requestUtils.getCurrentIp() + "->" + methodName;

        // 獲取key對(duì)應(yīng)的RateLimiter
        RateLimiter rateLimiter = limiterCache.get(key, () -> RateLimiter.create(PERMIT_PER_SECOND));

        if (! rateLimiter.tryAcquire()) {
            // 如果不能立刻獲取令牌, 說(shuō)明訪問(wèn)速度大于1 次/s, 觸發(fā)限流
            log.warn("訪問(wèn)過(guò)快, 觸發(fā)限流");
            throw new RuntimeException("訪問(wèn)過(guò)快, 觸發(fā)限流");
        }
        log.info("接口放行...");
        return proceedingJoinPoint.proceed();
    }
}

RequestUtils.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class RequestUtils {

    @Autowired
    private HttpServletRequest httpServletRequest;

    public String getCurrentIp() {
        return httpServletRequest.getHeader("X-Real-IP");
    }
}

4. 接口測(cè)試

接口測(cè)試這塊就比較隨意了,筆者這里采用apifox進(jìn)行接口測(cè)試。因?yàn)锳OP邏輯是增強(qiáng)所有接口,因此這里選擇了項(xiàng)目曾經(jīng)暴露出的一個(gè)查詢接口。點(diǎn)擊運(yùn)行,即可開始測(cè)試
【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter),前后端的那些事,spring boot,限流,RateLimiter,令牌桶算法,漏斗算法

5. 測(cè)試結(jié)果

【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter),前后端的那些事,spring boot,限流,RateLimiter,令牌桶算法,漏斗算法
2.6s,分別在0,1,2s開始時(shí),允許接口訪問(wèn)。10個(gè)請(qǐng)求中通過(guò)3個(gè),失敗7個(gè),QPS = 1,限流成功

【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter),前后端的那些事,spring boot,限流,RateLimiter,令牌桶算法,漏斗算法
測(cè)試量達(dá)到40,QPS維持1,說(shuō)明代碼邏輯基本沒(méi)有問(wèn)題,Google yyds!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-854236.html

到了這里,關(guān)于【前后端的那些事】SpringBoot 基于內(nèi)存的ip訪問(wèn)頻率限制切面(RateLimiter)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【前后端的那些事】開源!快速上手富文本+富文本圖片上傳

    【前后端的那些事】開源!快速上手富文本+富文本圖片上傳

    前言 :最近寫項(xiàng)目,發(fā)現(xiàn)了一些很有意思的功能,想寫文章,錄視頻把這些內(nèi)容記錄下。但這些功能太零碎,如果為每個(gè)功能都單獨(dú)搭建一個(gè)項(xiàng)目,這明顯不合適。于是我想,就搭建一個(gè)項(xiàng)目,把那些我想將的小功能全部整合到一起。實(shí)現(xiàn) 搭一次環(huán)境 ,處處使用。 本文主要

    2024年01月20日
    瀏覽(23)
  • 【前后端的那些事】2萬(wàn)字詳解WebRTC + 入門demo代碼解析

    【前后端的那些事】2萬(wàn)字詳解WebRTC + 入門demo代碼解析

    WebRTC是一項(xiàng)允許網(wǎng)頁(yè)瀏覽器進(jìn)行實(shí)時(shí)音視頻通信的技術(shù)標(biāo)準(zhǔn)。旨在實(shí)現(xiàn)在瀏覽器之間直接進(jìn)行點(diǎn)對(duì)點(diǎn)的音頻、視頻以及數(shù)據(jù)共享,無(wú)需安裝任何插件或額外軟件。 ICE全稱Interactive Connectivity Establishment ,是一種交互式連接框架,他允許兩個(gè)設(shè)備進(jìn)行p2p通訊。 在進(jìn)行p2p通訊過(guò)程

    2024年03月11日
    瀏覽(20)
  • 基于Springboot 限制IP訪問(wèn)指定的網(wǎng)址

    添加一個(gè)簡(jiǎn)單的白名單,然后只有白名單上面的 IP 才能訪問(wèn)網(wǎng)站,否則不能訪問(wèn) 這是只是一個(gè)很簡(jiǎn)單的實(shí)現(xiàn)方法 首先:在 application.yml 配置 IP 白名單 想要引用到配置文件里面的 String 數(shù)組,如果使用普通的 @Value 是不行的,必須使用其他方法 步驟一:創(chuàng)建一個(gè)實(shí)體類 這樣配

    2024年01月18日
    瀏覽(45)
  • Nginx 限流模塊:限制高并發(fā)和IP訪問(wèn)頻率

    Nginx 限流模塊:限制高并發(fā)和IP訪問(wèn)頻率

    Nginx 是我們常用的負(fù)載均衡和反向代理服務(wù)器,并發(fā)性能非常優(yōu)秀。 但是在并發(fā)量極大的情況下,必要限流措施還是需要的,Nginx 的有對(duì)應(yīng)的模塊插件可通過(guò)簡(jiǎn)單配置來(lái)完成這個(gè)功能。 1、添加 limit_conn_zone 這個(gè)變量只能在http使用。

    2023年04月25日
    瀏覽(27)
  • 從零開始快速搭建SpringBoot+Mybatis+小程序應(yīng)用--微信小程序的入門和前后端的聯(lián)調(diào)

    從零開始快速搭建SpringBoot+Mybatis+小程序應(yīng)用--微信小程序的入門和前后端的聯(lián)調(diào)

    目錄 項(xiàng)目介紹 ?vx小程序簡(jiǎn)介 VX開發(fā)工具介紹 列表頁(yè)開發(fā) list的編寫? ?列表頁(yè)前后端聯(lián)調(diào) ?信息編輯頁(yè)開發(fā) operation的編寫 區(qū)域信息編輯頁(yè)的聯(lián)調(diào) 從0搭建后端的Springboot+mybatis框架 實(shí)現(xiàn)后端的業(yè)務(wù)功能 實(shí)現(xiàn)本地微信小程序的前端開發(fā) 前端與后端的調(diào)控 技術(shù)儲(chǔ)備要求 1.基礎(chǔ)的

    2024年02月10日
    瀏覽(34)
  • SpringBoot實(shí)現(xiàn)圖形驗(yàn)證碼功能+訪問(wèn)頻率設(shè)置+緩存

    SpringBoot實(shí)現(xiàn)圖形驗(yàn)證碼功能+訪問(wèn)頻率設(shè)置+緩存

    目錄 1、springboot實(shí)現(xiàn)圖形驗(yàn)證碼生成 1.1、導(dǎo)入Maven依賴 1.2、寫一個(gè)生成圖片的工具類 1.3、編寫接口生成驗(yàn)證碼并存入Redis 2、實(shí)現(xiàn)圖形驗(yàn)證碼判斷是否正確 2.1、編寫驗(yàn)證圖形驗(yàn)證碼接口 2.2、前端代碼 2.3、請(qǐng)求發(fā)送 3、實(shí)現(xiàn)訪問(wèn)頻率限制 3.1、創(chuàng)建自定義注解 3.2、創(chuàng)建自定義

    2024年04月17日
    瀏覽(26)
  • 進(jìn)度變動(dòng)實(shí)時(shí)通知-使用SocketIO實(shí)現(xiàn)前后端的通信(基于WebSocket的實(shí)時(shí)通信庫(kù))

    進(jìn)度變動(dòng)實(shí)時(shí)通知-使用SocketIO實(shí)現(xiàn)前后端的通信(基于WebSocket的實(shí)時(shí)通信庫(kù))

    最近在接觸的一個(gè)項(xiàng)目,將PDF上傳到項(xiàng)目里,通過(guò)調(diào)用OCR云服務(wù)把PDF里的表格數(shù)據(jù)識(shí)別出來(lái)。在此過(guò)程中,前后端需要實(shí)時(shí)通信,對(duì)識(shí)別數(shù)據(jù)進(jìn)行“進(jìn)度跟蹤”。因此我們采用SocketIO的通訊方式,識(shí)別中前端和后端服務(wù)建立SocketIO連接,根據(jù)事件進(jìn)行數(shù)據(jù)的實(shí)時(shí)更新百分比進(jìn)度

    2024年02月06日
    瀏覽(26)
  • SpringBoot限制接口訪問(wèn)頻率 - 這些錯(cuò)誤千萬(wàn)不能犯

    最近在基于SpringBoot做一個(gè)面向普通用戶的系統(tǒng),為了保證系統(tǒng)的穩(wěn)定性,防止被惡意攻擊,我想控制用戶訪問(wèn)每個(gè)接口的頻率。為了實(shí)現(xiàn)這個(gè)功能,可以設(shè)計(jì)一個(gè)annotation,然后借助AOP在調(diào)用方法之前檢查當(dāng)前ip的訪問(wèn)頻率,如果超過(guò)設(shè)定頻率,直接返回錯(cuò)誤信息。 在開始介

    2024年02月05日
    瀏覽(16)
  • nginx 前后的分離 (ip/域名)訪問(wèn) 負(fù)載均衡

    nginx 前后的分離 (ip/域名)訪問(wèn) 負(fù)載均衡

    首先前端隨便訪問(wèn)后端的一個(gè)端口,后端監(jiān)聽這個(gè)端口進(jìn)行服務(wù)轉(zhuǎn)發(fā)。 比如:8888 然后nginx在我們的服務(wù)器上部署兩個(gè)后端 這里我用docker部署了兩個(gè) 當(dāng)然你也可以在兩個(gè)服務(wù)器上面部署兩個(gè)后端,只要在nginx配置代理的時(shí)候修改一下ip就可以了。 nginx配置

    2024年04月29日
    瀏覽(32)
  • TCP/IP網(wǎng)絡(luò)編程(1)——基于TCP的服務(wù)端和客戶端的簡(jiǎn)單實(shí)現(xiàn)

    目錄 前言 一、服務(wù)器端函數(shù) 1. 創(chuàng)建套接字函數(shù) socket 2. 套接字綁定地址函數(shù) bind 3. 等待連接請(qǐng)求函數(shù) listen 4. 處理連接請(qǐng)求函數(shù) accept 5. 關(guān)閉套接字函數(shù) close 二、客戶端函數(shù) 1. 請(qǐng)求連接函數(shù) connect 三、完整代碼 四、 基于TCP的半關(guān)閉 shutdown 五、 套接字可選項(xiàng) getsockopt setsoc

    2024年02月07日
    瀏覽(32)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包