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

中小型項(xiàng)目請(qǐng)求限流設(shè)計(jì)

這篇具有很好參考價(jià)值的文章主要介紹了中小型項(xiàng)目請(qǐng)求限流設(shè)計(jì)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

何為請(qǐng)求限流?

請(qǐng)求限流是一種控制API或其他Web服務(wù)的流量的技術(shù)。它的目的是限制客戶端對(duì)服務(wù)器發(fā)出的請(qǐng)求的數(shù)量或速率,以防止服務(wù)器過載或響應(yīng)時(shí)間變慢,從而提高系統(tǒng)的可用性和穩(wěn)定性。

中小型項(xiàng)目請(qǐng)求限流的需求

  1. 按IP、用戶、全局限流
  2. 基于不同實(shí)現(xiàn)的限流設(shè)計(jì)(基于Redis或者LRU緩存)
  3. 基于注解標(biāo)注哪些接口限流

完整限流設(shè)計(jì)實(shí)現(xiàn)在開源項(xiàng)目中:https://github.com/valarchie/AgileBoot-Back-End

注解設(shè)計(jì)

聲明一個(gè)注解類,主要有以下幾個(gè)屬性

  • key(緩存的key)
  • time(時(shí)間范圍)
  • maxCount(時(shí)間范圍內(nèi)最大的請(qǐng)求次數(shù))
  • limitType(按IP/用戶/全局進(jìn)行限流)
  • cacheType(基于Redis或者M(jìn)ap來實(shí)現(xiàn)限流)
/**
 * 限流注解
 *
 * @author valarchie
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimit {

    /**
     * 限流key
     */
    String key() default "None";

    /**
     * 限流時(shí)間,單位秒
     */
    int time() default 60;

    /**
     * 限流次數(shù)
     */
    int maxCount() default 100;

    /**
     * 限流條件類型
     */
    LimitType limitType() default LimitType.GLOBAL;

    /**
     * 限流使用的緩存類型
     */
    CacheType cacheType() default CacheType.REDIS;

}

LimitType枚舉,我們可以將不同限制類型的邏輯直接放在枚舉類當(dāng)中。推薦將邏輯直接放置在枚舉類中,代碼的組織形式會(huì)更好。

enum LimitType {
        /**
         * 默認(rèn)策略全局限流  不區(qū)分IP和用戶
         */
        GLOBAL{
            @Override
            public String generateCombinedKey(RateLimit rateLimiter) {
                return rateLimiter.key() + this.name();
            }
        },

        /**
         * 根據(jù)請(qǐng)求者IP進(jìn)行限流
         */
        IP {
            @Override
            public String generateCombinedKey(RateLimit rateLimiter) {
                String clientIP = ServletUtil.getClientIP(ServletHolderUtil.getRequest());
                return rateLimiter.key() + clientIP;
            }
        },

        /**
         * 按用戶限流
         */
        USER {
            @Override
            public String generateCombinedKey(RateLimit rateLimiter) {
                LoginUser loginUser = AuthenticationUtils.getLoginUser();
                if (loginUser == null) {
                    throw new ApiException(ErrorCode.Client.COMMON_NO_AUTHORIZATION);
                }
                return rateLimiter.key() + loginUser.getUsername();
            }
        };

        public abstract String generateCombinedKey(RateLimit rateLimiter);

    }
    

CacheType, 主要分為Redis和Map, 后續(xù)有新的類型可以新增。


  enum CacheType {

      /**
       * 使用redis做緩存
       */
      REDIS,

      /**
       * 使用map做緩存
       */
      Map

  }


RateLimitChecker設(shè)計(jì)

聲明一個(gè)抽象類,然后將具體實(shí)現(xiàn)放在實(shí)現(xiàn)類中,便于擴(kuò)展

/**
 * @author valarchie
 */
public abstract class AbstractRateLimitChecker {

    /**
     * 檢查是否超出限流
     * @param rateLimiter
     */
    public abstract void check(RateLimit rateLimiter);

}

Redis限流實(shí)現(xiàn)

/**
 * @author valarchie
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class RedisRateLimitChecker extends AbstractRateLimitChecker{

    @NonNull
    private RedisTemplate<Object, Object> redisTemplate;

    private final RedisScript<Long> limitScript = new DefaultRedisScript<>(limitScriptText(), Long.class);

    @Override
    public void check(RateLimit rateLimiter) {
        int maxCount = rateLimiter.maxCount();
        String combineKey = rateLimiter.limitType().generateCombinedKey(rateLimiter);

        Long currentCount;
        try {
            currentCount = redisTemplate.execute(limitScript, ListUtil.of(combineKey), maxCount, rateLimiter.time());
            log.info("限制請(qǐng)求:{}, 當(dāng)前請(qǐng)求次數(shù):{}, 緩存key:{}", combineKey, currentCount, rateLimiter.key());
        } catch (Exception e) {
            throw new RuntimeException("redis限流器異常,請(qǐng)確保redis啟動(dòng)正常");
        }

        if (currentCount == null) {
            throw new RuntimeException("redis限流器異常,請(qǐng)稍后再試");
        }

        if (currentCount.intValue() > maxCount) {
            throw new ApiException(ErrorCode.Client.COMMON_REQUEST_TOO_OFTEN);
        }

    }

    /**
     * 限流腳本
     */
    private static String limitScriptText() {
        return "local key = KEYS[1]\n" +
            "local count = tonumber(ARGV[1])\n" +
            "local time = tonumber(ARGV[2])\n" +
            "local current = redis.call('get', key);\n" +
            "if current and tonumber(current) > count then\n" +
            "    return tonumber(current);\n" +
            "end\n" +
            "current = redis.call('incr', key)\n" +
            "if tonumber(current) == 1 then\n" +
            "    redis.call('expire', key, time)\n" +
            "end\n" +
            "return tonumber(current);";
    }

}

Map + Guava RateLimiter實(shí)現(xiàn)

/**
 * @author valarchie
 */
@SuppressWarnings("UnstableApiUsage")
@Component
@RequiredArgsConstructor
@Slf4j
public class MapRateLimitChecker extends AbstractRateLimitChecker{

    /**
     * 最大僅支持4096個(gè)key   超出這個(gè)key  限流將可能失效
     */
    private final LRUCache<String, RateLimiter> cache = new LRUCache<>(4096);


    @Override
    public void check(RateLimit rateLimit) {
        String combinedKey = rateLimit.limitType().generateCombinedKey(rateLimit);

        RateLimiter rateLimiter = cache.get(combinedKey,
            () -> RateLimiter.create((double) rateLimit.maxCount() / rateLimit.time())
        );

        if (!rateLimiter.tryAcquire()) {
            throw new ApiException(ErrorCode.Client.COMMON_REQUEST_TOO_OFTEN);
        }

        log.info("限制請(qǐng)求key:{}, combined key:{}", rateLimit.key(), combinedKey);
    }

}

限流切面

我們需要在切面中,讀取限流注解標(biāo)注的信息,然后選擇不同的限流實(shí)現(xiàn)來進(jìn)行限流。

/**
 * 限流切面處理
 *
 * @author valarchie
 */
@Aspect
@Component
@Slf4j
@ConditionalOnExpression("'${agileboot.embedded.redis}' != 'true'")
@RequiredArgsConstructor
public class RateLimiterAspect {

    @NonNull
    private RedisRateLimitChecker redisRateLimitChecker;

    @NonNull
    private MapRateLimitChecker mapRateLimitChecker;


    @Before("@annotation(rateLimiter)")
    public void doBefore(JoinPoint point, RateLimit rateLimiter) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        log.info("當(dāng)前限流方法:" + method.toGenericString());

        switch (rateLimiter.cacheType()) {
            case REDIS:
                redisRateLimitChecker.check(rateLimiter);
                break;
            case Map:
                mapRateLimitChecker.check(rateLimiter);
                return;
            default:
                redisRateLimitChecker.check(rateLimiter);
        }

    }

}

注解使用

以下是我們標(biāo)注的注解例子。

time=10,maxCount=10表明10秒內(nèi)最多10次請(qǐng)求。

cacheType=Redis表明使用Redis來實(shí)現(xiàn)。

limitType=IP表明基于IP來限流。

/**
 * 生成驗(yàn)證碼
 */
@Operation(summary = "驗(yàn)證碼")
@RateLimit(key = RateLimitKey.LOGIN_CAPTCHA_KEY, time = 10, maxCount = 10, cacheType = CacheType.REDIS,
    limitType = LimitType.IP)
@GetMapping("/captchaImage")
public ResponseDTO<CaptchaDTO> getCaptchaImg() {
    CaptchaDTO captchaImg = loginService.generateCaptchaImg();
    return ResponseDTO.ok(captchaImg);
}

這是筆者關(guān)于中小型項(xiàng)目關(guān)于請(qǐng)求限流的實(shí)現(xiàn),如有不足歡迎大家評(píng)論指正。文章來源地址http://www.zghlxwxcb.cn/news/detail-409888.html

全棧技術(shù)交流群:1398880

到了這里,關(guān)于中小型項(xiàng)目請(qǐng)求限流設(shè)計(jì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(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)文章

  • 中小型超市的網(wǎng)絡(luò)規(guī)劃與設(shè)計(jì)(完整文檔+思科拓?fù)鋱D)

    中小型超市的網(wǎng)絡(luò)規(guī)劃與設(shè)計(jì)(完整文檔+思科拓?fù)鋱D)

    大家好,我是小華學(xué)長,一名計(jì)算機(jī)領(lǐng)域的博主。經(jīng)過多年的學(xué)習(xí)和實(shí)踐,我積累了豐富的計(jì)算機(jī)知識(shí)和經(jīng)驗(yàn),在這里我想與大家分享我的學(xué)習(xí)心得和技巧,幫助你成為更好的程序員。 作為一名計(jì)算機(jī)博主,我一直專注于編程、算法、軟件開發(fā)等領(lǐng)域,在這些方面積累了大量

    2024年02月03日
    瀏覽(24)
  • 【計(jì)算機(jī)三級(jí)網(wǎng)絡(luò)技術(shù)】 第二篇 中小型系統(tǒng)總體規(guī)劃與設(shè)計(jì)

    【計(jì)算機(jī)三級(jí)網(wǎng)絡(luò)技術(shù)】 第二篇 中小型系統(tǒng)總體規(guī)劃與設(shè)計(jì)

    基于網(wǎng)絡(luò)的信息系統(tǒng)結(jié)構(gòu)應(yīng)包括 網(wǎng)絡(luò)運(yùn)行環(huán)境、網(wǎng)絡(luò)系統(tǒng)、網(wǎng)絡(luò)操作系統(tǒng)。 網(wǎng)絡(luò)運(yùn)行環(huán)境指為了保障網(wǎng)絡(luò)系統(tǒng)安全、可靠與正常運(yùn)行所需的基本設(shè)施和設(shè)備條件,主要包括 機(jī)房與電源 兩部分。 (1)機(jī)房和設(shè)備間、配線間。 機(jī)房用于放置交換機(jī)、核心路由器、服務(wù)器等核心

    2024年02月09日
    瀏覽(25)
  • 9.3K+ Star!一個(gè)面向中小型企業(yè)設(shè)計(jì)的開源運(yùn)維平臺(tái)!

    大家好,我是 Java陳序員 。 我們?cè)谌粘i_發(fā)中,會(huì)有很多的應(yīng)用環(huán)境, 開發(fā)環(huán)境、測(cè)試環(huán)境、回歸環(huán)境、生產(chǎn)環(huán)境 等等。 這些環(huán)境,需要部署在一臺(tái)臺(tái)的服務(wù)器上,有的可能是物理機(jī),有的可能是云服務(wù)器。 那么,這么多主機(jī)我們要怎么運(yùn)維整理呢? 今天,給大家介紹一

    2024年02月05日
    瀏覽(23)
  • Cisco Packet Trancer中小型校園網(wǎng)/企業(yè)網(wǎng)/園區(qū)網(wǎng)網(wǎng)絡(luò)設(shè)計(jì)規(guī)劃/無線網(wǎng)絡(luò)

    Cisco Packet Trancer中小型校園網(wǎng)/企業(yè)網(wǎng)/園區(qū)網(wǎng)網(wǎng)絡(luò)設(shè)計(jì)規(guī)劃/無線網(wǎng)絡(luò)

    ?有需求,見評(píng)論私信交流?。。?項(xiàng)目演示視頻: Cisco PT軟件模擬實(shí)現(xiàn)雙核心中型企業(yè)/校園網(wǎng) 網(wǎng)絡(luò)架構(gòu)拓?fù)湓O(shè)計(jì)、論文,畢設(shè)_嗶哩嗶哩_bilibili 例1: ? ? ? 目錄 摘要 一、 緒論 (一)項(xiàng)目背景分析 (二) 企業(yè)園區(qū)網(wǎng)發(fā)展現(xiàn)狀 二、系統(tǒng)需求分析 (一)項(xiàng)目背景分析 (二)

    2024年02月09日
    瀏覽(27)
  • 中小型企業(yè)網(wǎng)絡(luò)的組建

    中小型企業(yè)網(wǎng)絡(luò)的組建

    某企業(yè)計(jì)劃建設(shè)自己的企業(yè)園區(qū)網(wǎng)絡(luò),希望通過這個(gè)新建的網(wǎng)絡(luò)提供一個(gè)安全、可靠、可擴(kuò)展、高效的網(wǎng)絡(luò)環(huán)境,將兩個(gè)辦公地點(diǎn)連接到一起,使企業(yè)內(nèi)能夠方便快捷地實(shí)現(xiàn)網(wǎng)絡(luò)資源共享、全網(wǎng)接入Internet等目標(biāo),同時(shí)實(shí)現(xiàn)公司內(nèi)部的信息保密隔離,以及對(duì)于公網(wǎng)的安全訪問

    2024年02月08日
    瀏覽(24)
  • 中小型企業(yè)網(wǎng)網(wǎng)絡(luò)搭建ensp模擬

    中小型企業(yè)網(wǎng)網(wǎng)絡(luò)搭建ensp模擬

    本期模擬中小型企業(yè)的萬能組網(wǎng),該場景為總部與分部之間的跨運(yùn)營商互訪,如果拆開來,就是小型企業(yè)的內(nèi)網(wǎng)環(huán)境,技術(shù)可以任意搭配 場景1:總部部署STPRSTPVRRPOSPF靜態(tài),基于防火墻的GRE VPNIPSEC VPN、NAT 場景2:總部部署STPMSTPVRRP負(fù)載OSPF靜態(tài),基于防火墻的GRE VPNIPSEC

    2024年02月07日
    瀏覽(29)
  • ensp典型中小型企業(yè)網(wǎng)搭建(帶無線)

    ensp典型中小型企業(yè)網(wǎng)搭建(帶無線)

    該設(shè)計(jì)規(guī)劃的是一個(gè)公司的網(wǎng)絡(luò)搭建,采用接入層、核心層、匯聚層三層網(wǎng)絡(luò)。所有接入層匯聚層交換機(jī)運(yùn)行MSTP和VRRP協(xié)議,做冗余備份,保護(hù)設(shè)備和鏈路穩(wěn)定性。運(yùn)行ospf動(dòng)態(tài)路由協(xié)議,方便路由維護(hù)。使用dhcp動(dòng)態(tài)分配地址,便于ip地址管理。出口采用防火墻設(shè)備,保護(hù)網(wǎng)絡(luò)

    2024年02月05日
    瀏覽(35)
  • 企業(yè)知識(shí)庫搭建全流程,中小型企業(yè)必看

    企業(yè)知識(shí)庫搭建全流程,中小型企業(yè)必看

    知識(shí)庫是企業(yè)知識(shí)管理和信息查詢的重要平臺(tái),對(duì)企業(yè)效率提升,業(yè)務(wù)流程規(guī)范和企業(yè)文化建設(shè)有著重要的影響。那么,如何為企業(yè)搭建一個(gè)合適,高效,易用的知識(shí)庫呢?接下來就為中小型企業(yè)詳解企業(yè)知識(shí)庫搭建全流程。 1.明確知識(shí)庫的目的和目標(biāo)受眾 首先,你需要明確

    2024年01月16日
    瀏覽(36)
  • ssm中小型企業(yè)財(cái)務(wù)管理系統(tǒng)源碼和論文

    ssm中小型企業(yè)財(cái)務(wù)管理系統(tǒng)源碼和論文

    ssm中小型企業(yè)財(cái)務(wù)管理系統(tǒng)源碼和論文067 ?開發(fā)工具:idea? ?數(shù)據(jù)庫mysql5.7+ ?數(shù)據(jù)庫鏈接工具:navcat,小海豚等 ? 技術(shù):ssm 1、研究目的意義 社會(huì)經(jīng)濟(jì)的迅速發(fā)展和科學(xué)技術(shù)的全面進(jìn)步,計(jì)算機(jī)技術(shù)的飛速發(fā)展,以及計(jì)算機(jī)與通信技術(shù)為基礎(chǔ)的信息系統(tǒng)正處于蓬勃發(fā)展的時(shí)期

    2024年02月11日
    瀏覽(107)
  • 無線AP中小型、大型兩種常見組網(wǎng)方式

    無線AP中小型、大型兩種常見組網(wǎng)方式

    無線AP(Access Point)網(wǎng)絡(luò)覆蓋是現(xiàn)代無線網(wǎng)絡(luò)中的重要組成部分。它提供了無線信號(hào)的傳輸和接收功能,使用戶能夠在無線網(wǎng)絡(luò)中進(jìn)行通信和訪問互聯(lián)網(wǎng)。針對(duì)不同的需求和場景,存在兩種常見的無線AP網(wǎng)絡(luò)覆蓋組網(wǎng)方式:中小型的無線覆蓋組網(wǎng)方式和大范圍的無線覆蓋組網(wǎng)方

    2024年02月06日
    瀏覽(18)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包