欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot如何使用RateLimiter通過AOP方式進行限流

 更新時間:2022年06月07日 11:18:40   作者:yellow_han  
這篇文章主要介紹了SpringBoot如何使用RateLimiter通過AOP方式進行限流,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

使用RateLimiter通過AOP方式進行限流

1、引入依賴

<!-- guava 限流 -->
<dependency>
?? ? <groupId>com.google.guava</groupId>
?? ? <artifactId>guava</artifactId>
?? ? <version>25.1-jre</version>
</dependency>

2、自定義注解

@Target({ElementType.PARAMETER, ElementType.METHOD}) ? ?
@Retention(RetentionPolicy.RUNTIME) ? ?
@Documented ? ?
public ?@interface ServiceLimit {?
?? ? String description() ?default "";
}

3、AOP實現(xiàn)類

@Component
@Scope
@Aspect
public class LimitAspect {
?? ?每秒只發(fā)出5個令牌,此處是單進程服務(wù)的限流,內(nèi)部采用令牌捅算法實現(xiàn)
?? ?private static ? RateLimiter rateLimiter = RateLimiter.create(5.0);
?? ?
?? ?//Service層切點 ?限流
?? ?@Pointcut("@annotation(com.itstyle.seckill.common.aop.ServiceLimit)") ?
?? ?public void ServiceAspect() {
?? ??? ?
?? ?}
?? ?
? ? @Around("ServiceAspect()")
? ? public ?Object around(ProceedingJoinPoint joinPoint) {?
? ? ?? ?Boolean flag = rateLimiter.tryAcquire();
? ? ?? ?Object obj = null;
?? ??? ?try {
?? ??? ??? ?if(flag){
?? ??? ??? ??? ?obj = joinPoint.proceed();
?? ??? ??? ?}
?? ??? ?} catch (Throwable e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}?
? ? ?? ?return obj;
? ? }?
}

4、使用

@Override
@ServiceLimit
@Transactional
?? ?public Result startSeckil(long seckillId,long userId) {
?? ??? ?//todo 操作
?? ?}

SpringBoot之限流

限流的基礎(chǔ)算法

令牌桶和漏桶

  • 漏桶算法 的實現(xiàn)往往依賴于隊列,請求到達如果隊列未滿則直接放入隊列,然后有一個處理器按照固定頻率從隊列頭取出請求進行處理。如果請求量大,則會導(dǎo)致隊列滿,那么新來的請求就會被拋棄。
  • 令牌桶算法 則是一個存放固定容量令牌的桶,按照固定速率往桶里添加令牌。桶中存放的令牌數(shù)有最大上限,超出之后就被丟棄或者拒絕。當(dāng)流量或者網(wǎng)絡(luò)請求到達時,每個請求都要獲取一個令牌,如果能夠獲取到,則直接處理,并且令牌桶刪除一個令牌。如果獲取不到,該請求就要被限流,要么直接丟棄,要么在緩沖區(qū)等待。

令牌桶和漏桶對比

  • 令牌桶是按照固定速率往桶中添加令牌,請求是否被處理需要看桶中令牌是否足夠,當(dāng)令牌數(shù)減為零時則拒絕新的請求;漏桶則是按照常量固定速率流出請求,流入請求速率任意,當(dāng)流入的請求數(shù)累積到漏桶容量時,則新流入的請求被拒絕;
  • 令牌桶限制的是平均流入速率,允許突發(fā)請求,只要有令牌就可以處理,支持一次拿3個令牌,4個令牌;漏桶限制的是常量流出速率,即流出速率是一個固定常量值,比如都是1的速率流出,而不能一次是1,下次又是2,從而平滑突發(fā)流入速率;
  • 令牌桶允許一定程度的突發(fā),而漏桶主要目的是平滑流出速率;

Guava RateLimiter

1.依賴

<dependency>
? ? <groupId>com.google.guava</groupId>
? ? <artifactId>guava</artifactId>
? ? <version>28.1-jre</version>
? ? <optional>true</optional>
</dependency>

2.示例代碼 

@Slf4j
@Configuration
public class RequestInterceptor implements HandlerInterceptor {
    // 根據(jù)字符串分不同的令牌桶, 每天自動清理緩存
    private static LoadingCache<String, RateLimiter> cachesRateLimiter = CacheBuilder.newBuilder()
            .maximumSize(1000)  //設(shè)置緩存?zhèn)€數(shù)
            /**
             * expireAfterWrite是在指定項在一定時間內(nèi)沒有創(chuàng)建/覆蓋時,會移除該key,下次取的時候從loading中取
             * expireAfterAccess是指定項在一定時間內(nèi)沒有讀寫,會移除該key,下次取的時候從loading中取
             * refreshAfterWrite是在指定時間內(nèi)沒有被創(chuàng)建/覆蓋,則指定時間過后,再次訪問時,會去刷新該緩存,在新值沒有到來之前,始終返回舊值
             * 跟expire的區(qū)別是,指定時間過后,expire是remove該key,下次訪問是同步去獲取返回新值;
             * 而refresh則是指定時間后,不會remove該key,下次訪問會觸發(fā)刷新,新值沒有回來時返回舊值
             */
            .expireAfterAccess(1, TimeUnit.HOURS)
            .build(new CacheLoader<String, RateLimiter>() {
                @Override
                public RateLimiter load(String key) throws Exception {
                    // 新的字符串初始化 (限流每秒2個令牌響應(yīng))
                    return RateLimiter.create(2);
                }
            });
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        log.info("request請求地址path[{}] uri[{}]", request.getServletPath(), request.getRequestURI());
        try {
            String str = "hello";
            // 令牌桶
            RateLimiter rateLimiter = cachesRateLimiter.get(str);
            if (!rateLimiter.tryAcquire()) {
                System.out.println("too many requests.");
                return false;
            }
        } catch (Exception e) {
            // 解決攔截器的異常,全局異常處理器捕獲不到的問題
            request.setAttribute("exception", e);
            request.getRequestDispatcher("/error").forward(request, response);
        }
        return true;
    }
}

3.測試

@RestController
@RequestMapping(value = "user")
public class UserController {
    @GetMapping
    public Result test2(){
        System.out.println("1111");
        return new Result(true,200,"");
    }
}

http://localhost:8080/user/

如果沒有result類,自己可以隨便返回個字符串

4.測試結(jié)果

其他

創(chuàng)建

RateLimiter提供了兩個工廠方法:

  • 一個是平滑突發(fā)限流
RateLimiter r = RateLimiter.create(5); //項目啟動,直接允許5個令牌
  • 一個是平滑預(yù)熱限流
RateLimiter r = RateLimiter.create(2, 3, TimeUnit.SECONDS); //項目啟動后3秒后才會到達設(shè)置的2個令牌

缺點

RateLimiter只能用于單機的限流,如果想要集群限流,則需要引入redis或者阿里開源的sentinel中間件。

TimeUnit.SECONDS);` //項目啟動后3秒后才會到達設(shè)置的2個令牌

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • ThreadLocal的set方法原理示例解析

    ThreadLocal的set方法原理示例解析

    這篇文章主要為大家介紹了ThreadLocal的set方法原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • Java關(guān)鍵字this與super詳解用法

    Java關(guān)鍵字this與super詳解用法

    這篇文章主要介紹了Java關(guān)鍵字this與super的用法,this與super是類實例化時通往Object類通道的打通者;this和super在程序中由于其經(jīng)常被隱式的使用而被我們忽略,但是理解其作用和使用規(guī)范肯定是必須的。接下來將詳述this與super各自的的作用,需要的朋友可以參考一下
    2022-04-04
  • Java多線程Condition接口原理介紹

    Java多線程Condition接口原理介紹

    這篇文章主要介紹了Java多線程Condition接口原理介紹,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java高性能本地緩存框架Caffeine的實現(xiàn)

    Java高性能本地緩存框架Caffeine的實現(xiàn)

    本文主要介紹了Java高性能本地緩存框架Caffeine的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • SpringBoot實現(xiàn)文件上傳接口

    SpringBoot實現(xiàn)文件上傳接口

    這篇文章主要為大家詳細介紹了SpringBoot實現(xiàn)文件上傳接口,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Java基于jdbc連接mysql數(shù)據(jù)庫操作示例

    Java基于jdbc連接mysql數(shù)據(jù)庫操作示例

    這篇文章主要介紹了Java基于jdbc連接mysql數(shù)據(jù)庫操作,結(jié)合完整實例形式分析了java使用jdbc連接mysql數(shù)據(jù)庫的具體步驟與相關(guān)注意事項,需要的朋友可以參考下
    2017-07-07
  • C語言實現(xiàn)矩陣運算案例詳解

    C語言實現(xiàn)矩陣運算案例詳解

    這篇文章主要介紹了C語言實現(xiàn)矩陣運算案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java聊天室之實現(xiàn)客戶端一對一聊天功能

    Java聊天室之實現(xiàn)客戶端一對一聊天功能

    這篇文章主要為大家詳細介紹了Java簡易聊天室之實現(xiàn)客戶端一對一聊天功能,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的可以了解一下
    2022-10-10
  • 理解Java注解及Spring的@Autowired是如何實現(xiàn)的

    理解Java注解及Spring的@Autowired是如何實現(xiàn)的

    今天通過本文帶領(lǐng)大家學(xué)習(xí)注解的基礎(chǔ)知識,學(xué)習(xí)Spring的@Autowired是怎么實現(xiàn)的,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-07-07
  • Java中序列化和反序列化的完整講解

    Java中序列化和反序列化的完整講解

    序列化是將對象轉(zhuǎn)換成二進制字節(jié)流的過程;反序列化是從二進制字節(jié)流中恢復(fù)對象的過程。文中將為大家詳細講講二者的原理與實現(xiàn),需要的可以參考一下
    2022-11-11

最新評論