精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

API接口限流竟然如此簡單

開發 前端
我們已經成功實現了一個基于Redisson和Spring AOP的API接口限流功能。這個方案不僅簡單易懂,而且非常靈活,可以通過注解輕松地應用到任意方法上,并且支持多種限流策略(如全局限流、IP限流、集群限流等)。

簡介

API接口限流是一種流量控制技術,其目的是通過設置規則來限制客戶端對API接口的調用速率或總量,從而避免因過載而導致的服務性能下降甚至崩潰。

API限流在各種系統上都會有廣泛的使用場景,本文介紹一種非常簡單的實現API限流的方式。

為什么需要API接口限流?

  • 防止惡意攻擊:通過限制請求速率,可以有效抵御DDoS等類型的攻擊。
  • 優化資源使用:合理分配有限的計算資源給所有用戶,避免單個用戶占用過多資源。
  • 提升服務質量:保持服務響應時間在一個合理的范圍內,提高整體用戶體驗。

令牌桶

常見的API限流策略有令牌桶等算法。

令牌桶算法是一種常用的流量控制和限流機制,它通過模擬一個存放“令牌”的桶來控制請求的速率。

這個算法的核心思想是:系統以恒定的速率向桶中添加令牌,而每個請求在被處理之前必須從桶中獲取一個令牌。如果桶中有足夠的令牌,則請求可以繼續執行;如果沒有足夠的令牌(即桶為空),則請求要么等待直到有新的令牌產生,要么直接被拒絕。

實現API限流

這個算法很容易理解,但是要想手動實現一個令牌桶算法,并不是一個容易的事情。

還需要考慮:時間精度、并發處理、存儲管理、可配置性等問題。

Redis是一個常用的非關系型數據庫,非常適合用于緩存、實現限流等功能。本文介紹一個利用redis非常簡單的實現限流的功能,采用 AOP + 注解 + Redisson 框架實現。

1.定義限流注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter {
    /**
     * 限流key,支持使用Spring el表達式來動態獲取方法上的參數值
     * 格式類似于  #code.id #{#code}
     */
    String key() default "";

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

    /**
     * 限流次數
     */
    int count() default 100;

    /**
     * 限流類型
     */
    LimitType limitType() default LimitType.DEFAULT;

    /**
     * 提示消息
     */
    String message() default "服務器暫無資源處理新的請求,請稍后重試";
}
public enum LimitType {
    /**
     * 默認策略全局限流
     */
    DEFAULT,

    /**
     * 根據請求者IP進行限流
     */
    IP,

    /**
     * 實例限流(集群多后端實例)
     */
    CLUSTER
}

2.注解切面

@Slf4j
@Aspect
@Order(1)
public class RateLimiterAspect {
    private static final String LIMITER_KEY = "global:limiter:";

    /**
     * 定義spel表達式解析器
     */
    private final ExpressionParser parser = new SpelExpressionParser();
    /**
     * 定義spel解析模版
     */
    private final ParserContext parserContext = new TemplateParserContext();
    /**
     * 方法參數解析器
     */
    private final ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();

    /**
     * \@within(rateLimiter) 和 \@annotation(rateLimiter) 必須按照這個順序,才會優先執行方法上的注解
     */
    @Before("@within(rateLimiter) || @annotation(rateLimiter)")
    public void doBefore(JoinPoint point, RateLimiter rateLimiter) {
        if (rateLimiter == null) {
            // 如果方法上沒有,就從類上獲取注解
            Class<?> targetClass = point.getTarget().getClass();
            rateLimiter = targetClass.getAnnotation(RateLimiter.class);
            if (rateLimiter == null) {
                // 如果還是沒有獲取到注解,直接返回
                return;
            }
        }
        int time = rateLimiter.time();
        int count = rateLimiter.count();
        try {
            String combineKey = getCombineKey(rateLimiter, point);
            RateType rateType = RateType.OVERALL;
            if (rateLimiter.limitType() == LimitType.CLUSTER) {
                rateType = RateType.PER_CLIENT;
            }
            long number = RedisUtils.rateLimiter(combineKey, rateType, count, time);
            if (number == -1) {
                throw new RateLimiterException(rateLimiter.message());
            }
            log.debug("限制令牌 => {}, 剩余令牌 => {}, 緩存key => '{}'", count, number, combineKey);
        } catch (Exception e) {
            if (e instanceof RateLimiterException) {
                throw e;
            } else {
                throw new RuntimeException("服務器限流異常,請稍候再試", e);
            }
        }
    }

    private String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
        String key = rateLimiter.key();
        // 判斷 key 不為空 和 不是表達式
        if (StringUtils.hasText(key) && key.contains("#")) {
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method targetMethod = signature.getMethod();
            Object[] args = point.getArgs();
            MethodBasedEvaluationContext context =
                new MethodBasedEvaluationContext(null, targetMethod, args, pnd);
            context.setBeanResolver(new BeanFactoryResolver(SpringUtil.getBeanFactory()));
            Expression expression;
            if (key.startsWith(parserContext.getExpressionPrefix()) && key.endsWith(parserContext.getExpressionSuffix())) {
                expression = parser.parseExpression(key, parserContext);
            } else {
                expression = parser.parseExpression(key);
            }
            key = expression.getValue(context, String.class);
        }
        StringBuilder str = new StringBuilder(LIMITER_KEY);
        HttpServletRequest request = getRequest();
        str.append(request.getRequestURI()).append(":");
        if (rateLimiter.limitType() == LimitType.IP) {
            // 獲取請求ip
            str.append(ServletUtil.getClientIP(request)).append(":");
        } else if (rateLimiter.limitType() == LimitType.CLUSTER) {
            // 獲取客戶端實例id
            str.append(RedisUtils.getClient().getId()).append(":");
        }
        return str.append(key).toString();
    }

    /**
     * 獲取request
     */
    private HttpServletRequest getRequest() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            return attributes.getRequest();
        } catch (Exception e) {
            return null;
        }
    }
}

3.Redisson 限流工具類

public class RedisUtils {

    private static final RedissonClient CLIENT = SpringUtil.getBean(RedissonClient.class);

    /**
     * 限流
     *
     * @param key          限流key
     * @param rateType     限流類型
     * @param rate         速率
     * @param rateInterval 速率間隔
     * @return -1 表示失敗
     */
    public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) {
        RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
        // 如果限流器存在
        if (rateLimiter.isExists()) {
            // 獲取上次限流的配置信息
            RateLimiterConfig rateLimiterConfig = rateLimiter.getConfig();
            // 如果rateLimiterConfig的配置跟我們注解上面的值不一致,說明服務器重啟過,程序員又修改了限流的配置
            if (TimeUnit.SECONDS.convert(rateLimiterConfig.getRateInterval(), TimeUnit.MILLISECONDS) != rateInterval || rateLimiterConfig.getRate() != rate) {
                rateLimiter.delete();
                rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
            }
        }
        rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
        if (rateLimiter.tryAcquire()) {
            return rateLimiter.availablePermits();
        } else {
            return -1L;
        }
    }
    
    /**
     * 獲取客戶端實例
     */
    public static RedissonClient getClient() {
        return CLIENT;
    }
}

4.捕獲異常

@Data
@EqualsAndHashCode(callSuper = true)
public class RateLimiterException extends RuntimeException {

    /**
     * 錯誤提示
     */
    private final String message;

    public RateLimiterException(String message) {
        this.message = message;
    }

}
@Slf4j
@Order(1)
@RestControllerAdvice
public class LimiterExceptionHandler {

    /**
     * 限流異常
     */
    @ExceptionHandler({RateLimiterException.class})
    public Map<String, Object> handleRateLimiterException(RateLimiterException e, HttpServletRequest request) {
        log.error("請求地址'{}', 限流異常'{}'", request.getRequestURI(), e.getMessage());
        return result(e.getMessage());
    }

    private Map<String, Object> result(String msg) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", 500);
        result.put("msg", msg);
        return result;
    }
}

到這里,已經實現了一個完整的API接口限流功能。

可以將之進一步封裝,作為一個springboot的starter,用于任意一個項目中。

小結

通過上述步驟,我們已經成功實現了一個基于Redisson和Spring AOP的API接口限流功能。這個方案不僅簡單易懂,而且非常靈活,可以通過注解輕松地應用到任意方法上,并且支持多種限流策略(如全局限流、IP限流、集群限流等)。

責任編輯:武曉燕 來源: Java技術指北
相關推薦

2020-12-28 07:47:35

動態代理AOP

2024-08-28 08:42:21

API接口限流

2021-12-09 09:02:53

JavaPDF文件iText

2021-12-08 10:36:46

JavaPDF文件

2024-09-09 11:35:35

2022-08-12 12:19:13

Cluster檢索集群

2020-06-19 17:49:23

建網

2018-08-27 08:31:25

InnoDBMySQL

2025-11-14 03:00:00

MySQL并發數據

2020-02-20 16:07:45

IT需求

2022-01-09 23:38:42

通信協議網絡

2022-02-23 20:42:40

HTMLmarkdownturndown

2022-07-08 14:35:05

Java組件LiteFlow

2010-08-25 21:50:36

配置DHCP

2021-05-14 07:45:07

Sentinel 接口限流

2020-11-24 08:02:26

API接口重構

2009-04-29 01:39:57

破解美萍萬象

2011-10-11 10:53:29

Ubuntu 11.1Gnome 3.2

2023-08-21 08:01:03

2011-09-15 10:35:12

Android應用IOS應用著裝搭配
點贊
收藏

51CTO技術棧公眾號

26uuu国产| 亚洲精品人成| 国产婷婷色一区二区在线观看| 国产精品欧美三级在线观看| 欧美日韩国产免费一区二区 | 中国av一区| 欧美日韩国产综合一区二区 | 草莓视频丝瓜在线观看丝瓜18| av电影一区二区| 国产精品自拍网| 国产乡下妇女做爰| 日本一本不卡| 亚洲国产小视频在线观看| 美女一区二区三区视频| av有码在线观看| 亚洲国产精品精华液ab| 国产精华一区二区三区| 国产高清中文字幕| 欧美午夜在线| 久久婷婷国产麻豆91天堂 | 亚洲黄色在线播放| 日本女优在线视频一区二区| 久久久视频在线| 欧美手机在线观看| 国内成人精品| 亚洲成人精品av| 伊人免费视频二| 91精品店在线| 一道本成人在线| 免费超爽大片黄| 成码无人av片在线观看网站| 国产欧美日韩在线看| 就去色蜜桃综合| 东京干手机福利视频| 韩国女主播成人在线| 国产精品黄色影片导航在线观看| 国产午夜在线播放| 国产精品vip| 美女精品视频一区| 制服丨自拍丨欧美丨动漫丨| 免费观看久久av| 亚洲精品v天堂中文字幕| 制服.丝袜.亚洲.中文.综合懂| 日本黄色成人| 在线电影欧美成精品| 污片在线免费看| 婷婷综合六月| 日韩欧美有码在线| 国产在线观看福利| 在线看片福利| 色综合 综合色| 亚洲精品中文字幕无码蜜桃| 蜜桃视频动漫在线播放| 欧美日韩国产黄| 色综合久久久久无码专区| 丰满的护士2在线观看高清| 亚洲一区二区三区四区中文字幕 | 丝袜国产在线| 一区二区在线电影| 屁屁影院ccyy国产第一页| 在线中文免费视频| 亚洲线精品一区二区三区| 国产高清不卡无码视频| 黄色羞羞视频在线观看| 亚洲大片免费看| 日本在线xxx| 制服丝袜专区在线| 色av成人天堂桃色av| 免费看黄色一级大片| 久久国内精品| 91麻豆精品国产91久久久使用方法 | 免费看一级一片| 欧美日韩三级| 18久久久久久| 中文无码av一区二区三区| 免费看黄色91| 91系列在线观看| 亚洲奶汁xxxx哺乳期| 91免费小视频| 亚洲高清资源综合久久精品| 激情成人四房播| 亚洲综合成人网| 色综合av综合无码综合网站| 欧美va在线观看| 51精品国自产在线| 国产乱淫av麻豆国产免费| 人妖一区二区三区| 一区二区三区无码高清视频| 欧美老熟妇一区二区三区| 国内精品久久久久久久97牛牛 | 熟女视频一区二区三区| 成人爽a毛片免费啪啪动漫 | 日本精品久久久久中文字幕| 午夜精品久久久久久毛片| 精品欧美乱码久久久久久1区2区 | 国产精品另类一区| 黄色成人在线免费观看| 色偷偷偷在线视频播放| 欧美二区在线观看| 久久人人妻人人人人妻性色av| 成人综合专区| 98精品国产自产在线观看| 中文在线资源天堂| 成人性生交大片免费看视频在线| 日韩成人av电影在线| 在线视频观看国产| 欧美在线|欧美| 人妻互换一二三区激情视频| 欧美精品一二| 91精品国产色综合久久不卡98| 伊人网av在线| 91视频免费看| av久久久久久| 欧美一级做a| 亚洲欧美一区二区三区久久| 久久久久无码国产精品不卡| 日本人妖一区二区| 精品日本一区二区三区| av片在线观看永久免费| 在线免费观看日本一区| 中文字幕三级电影| 亚洲乱码精品| 国产精品无av码在线观看| 五月婷在线视频| 一区二区三区四区av| 五月天中文字幕在线| 免费电影一区二区三区| 97在线视频精品| 精品久久久久中文慕人妻 | 亚洲国产古装精品网站| 精品无码久久久久成人漫画| 日韩av中文在线观看| 久久国产精品 国产精品| 青草在线视频| 6080午夜不卡| 欧美风情第一页| 蜜桃传媒麻豆第一区在线观看| 欧美系列一区| 成人欧美大片| 日韩精品免费在线观看| 日本三级视频在线| 成人免费福利片| 欧美大黑帍在线播放| 精品成人18| 久久精品色欧美aⅴ一区二区| 曰批又黄又爽免费视频| 国产欧美视频一区二区| 91视频免费版污| 欧美日韩一区二区综合| 国产成人精品免高潮费视频| 国产一区二区影视| 欧美在线三级电影| 少妇av片在线观看| 久久激情综合网| 中文字幕在线亚洲精品| 高清一区二区中文字幕| 欧美成人午夜激情在线| 丰满肥臀噗嗤啊x99av| 亚洲韩国一区二区三区| 国产国语性生话播放| 国产视频一区欧美| 天堂av一区二区| 日韩午夜电影免费看| 不卡av在线网站| 亚洲黄色片视频| 欧美日韩亚洲天堂| 男人的天堂av网| 国产一区不卡精品| 国产va亚洲va在线va| 日韩福利视频一区| 国产精品欧美日韩一区二区| aaa在线免费观看| 欧美一区二区女人| 久久艹精品视频| 26uuu色噜噜精品一区二区| 99久久国产宗和精品1上映 | 日韩在线高清视频| 国产女主播福利| 亚洲国产精品自拍| 丰腴饱满的极品熟妇| 美女视频第一区二区三区免费观看网站| 一区二区三区国| 国产成人澳门| 国产精品美女999| 日韩免费影院| 亚洲欧美制服综合另类| 91无套直看片红桃| 天天色天天操综合| 精品女人久久久| 99v久久综合狠狠综合久久| 能看的毛片网站| 欧美日本不卡高清| 日本一区二区久久精品| 91精品国产自产在线丝袜啪| 欧洲日韩成人av| 成人午夜在线影视| 亚洲性xxxx| 亚洲欧美黄色片| 在线日韩av片| 日韩无码精品一区二区三区| 日本一二三不卡| 私密视频在线观看| 久久国产精品一区二区| 波多野结衣家庭教师在线播放 | 国产免费观看高清视频| 欧美残忍xxxx极端| 美女三级99| 成人知道污网站| 国产区精品视频| 在线天堂资源www在线污| 九色成人免费视频| 自拍视频在线| 亚洲欧美激情精品一区二区| 国内精品国产成人国产三级| 欧美视频在线观看一区二区| 日产亚洲一区二区三区| 一区二区三区蜜桃网| 亚欧精品视频一区二区三区| 2020国产精品久久精品美国| 日本女人性视频| 久久国产精品99精品国产| 成年人免费大片| 一区二区三区高清视频在线观看| 9色视频在线观看| 99久久www免费| 亚洲国产精品毛片| 国产剧情一区| 蜜桃av色综合| 日韩精品导航| 好吊色欧美一区二区三区| 一区中文字幕| 91久久精品www人人做人人爽| 成人免费视频观看| 国产91在线播放| 波多野结衣久久精品| 97在线视频观看| 丁香花在线高清完整版视频 | 亚洲日本精品国产第一区| 伊人久久综合影院| 欧美日韩综合精品| 九九久久精品| 欧美中文娱乐网| 国产99久久精品一区二区300| 久久久久久九九| 欧美91在线| 欧美日韩电影一区二区三区| 欧洲精品一区| 欧美性xxxx69| 国产精品免费99久久久| 日韩精品一区二区三区色偷偷| 久操国产精品| 亚洲精品在线观看免费| 精品freesex老太交| 午夜欧美性电影| 久久国产精品亚洲人一区二区三区 | www.夜夜爽| 激情深爱一区二区| 香蕉视频1024| 26uuu色噜噜精品一区| 一级片视频免费看| 国产精品久久久久久一区二区三区| аⅴ天堂中文在线网| 中文字幕在线不卡国产视频| 三级黄色免费观看| 亚洲精选一二三| 精品在线视频免费观看| 欧美日韩加勒比精品一区| 亚洲黄网在线观看| 欧美日韩在线三级| 国产成人精品a视频| 亚洲精品成人网| 国产免费a∨片在线观看不卡| 在线播放日韩欧美| 久cao在线| 午夜精品美女自拍福到在线| 三级成人黄色影院| 91牛牛免费视频| 欧美日韩导航| 一区二区三区不卡在线| 日韩亚洲在线| 亚洲欧美视频二区| 成人精品鲁一区一区二区| 欧洲美一区二区三区亚洲| 亚洲日本va在线观看| 一区二区三区视频免费看| 欧美色图12p| 亚洲伦理在线观看| 亚洲色图偷窥自拍| a视频在线免费看| 国产999在线| 久久天堂久久| 日本婷婷久久久久久久久一区二区 | 久久久久久久黄色片| 欧美视频在线播放| 蜜桃视频在线观看www| 在线视频欧美日韩精品| 高清电影在线免费观看| 国产区精品在线观看| 麻豆一区二区| 中文字幕一区综合| 久久久噜噜噜久久狠狠50岁| 九九九久久久久久久| 久久精品亚洲麻豆av一区二区 | 91黄色在线观看| 亚洲精品综合网| 综合久久五月天| 久久青草伊人| 国产高清精品一区二区| 久久亚洲影视| 美女福利视频在线| 国产成人精品亚洲777人妖 | 国产精品自拍视频| 亚洲人挤奶视频| 日本男女交配视频| 国产中文字幕一区| 国产在线综合视频| 欧美性猛交99久久久久99按摩| www夜片内射视频日韩精品成人| 亚洲小视频在线观看| 亚洲少妇视频| 国产日韩精品推荐| 欧美在线国产| 性生生活大片免费看视频| 久久久噜噜噜久久人人看| 精品无码人妻一区二区三| 欧美二区乱c少妇| 午夜激情视频在线| 国产精品久久97| 美女毛片一区二区三区四区最新中文字幕亚洲 | 性高潮免费视频| 亚洲美女淫视频| 国产三级自拍视频| 精品国产一区二区三区久久狼黑人| 欧美日韩精品免费观看视完整| 国产亚洲情侣一区二区无| 欧美日韩一区二区国产| 绯色av蜜臀vs少妇| 伊人色综合久久天天| 国产jzjzjz丝袜老师水多| 日韩在线播放av| 97色婷婷成人综合在线观看| 亚洲精品9999| 九一九一国产精品| 国产又粗又长又黄的视频| 欧美系列一区二区| av男人的天堂在线| 国产欧美精品xxxx另类| 国产精品7m凸凹视频分类| 亚洲美女爱爱视频| 亚洲视频一区在线观看| 国产女18毛片多18精品| 久久视频免费观看| 秋霞一区二区三区| 成人在线视频一区二区三区| 国产成人在线视频网址| 久久精品视频8| 亚洲精品国产suv| 大胆人体一区| 午夜精品短视频| 久久av资源网| 久久久国产成人| 精品视频偷偷看在线观看| 蜜桃精品在线| 伊人久久99| 成人午夜视频在线| 在线观看中文字幕视频| 亚洲一区二区精品| 成人在线免费| 日本黄网站色大片免费观看| 粉嫩aⅴ一区二区三区四区| 欧美日韩精品区| 尤物九九久久国产精品的分类 | 大香伊人中文字幕精品| 蜜桃导航-精品导航| 久久国产精品第一页| 精品少妇一二三区| 亚洲片在线资源| 精品国产亚洲日本| 国产精品国产亚洲精品看不卡| 久久综合国产精品| 国产一区二区在线不卡| 欧美激情在线观看| 国产免费久久| 超碰人人cao| 一本色道久久综合亚洲精品按摩 | 日韩毛片在线免费观看| 成人毛片在线免费观看| 国产激情久久久久| 狠狠色狠狠色综合日日tαg| 国产三级av在线播放| 日韩久久精品一区| 亚洲成人一区在线观看| 欧美日韩午夜爽爽| 久久久久久久综合日本| 精品国产av一区二区| 国产999精品视频| 亚洲一级网站| 精品丰满少妇一区二区三区| 亚洲国产精品一区二区三区| 日韩国产91|