亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2022-06-07 13:46:08 來源:億速云 閱讀:368 作者:iii 欄目:開發技術

這篇文章主要講解了“SpringBoot怎么使用RateLimiter通過AOP方式進行限流”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“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實現類

@Component
@Scope
@Aspect
public class LimitAspect {
    每秒只發出5個令牌,此處是單進程服務的限流,內部采用令牌捅算法實現
    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之限流

限流的基礎算法

令牌桶和漏桶

  • 漏桶算法 的實現往往依賴于隊列,請求到達如果隊列未滿則直接放入隊列,然后有一個處理器按照固定頻率從隊列頭取出請求進行處理。如果請求量大,則會導致隊列滿,那么新來的請求就會被拋棄。

  • 令牌桶算法 則是一個存放固定容量令牌的桶,按照固定速率往桶里添加令牌。桶中存放的令牌數有最大上限,超出之后就被丟棄或者拒絕。當流量或者網絡請求到達時,每個請求都要獲取一個令牌,如果能夠獲取到,則直接處理,并且令牌桶刪除一個令牌。如果獲取不到,該請求就要被限流,要么直接丟棄,要么在緩沖區等待。

令牌桶和漏桶對比

  • 令牌桶是按照固定速率往桶中添加令牌,請求是否被處理需要看桶中令牌是否足夠,當令牌數減為零時則拒絕新的請求;漏桶則是按照常量固定速率流出請求,流入請求速率任意,當流入的請求數累積到漏桶容量時,則新流入的請求被拒絕;

  • 令牌桶限制的是平均流入速率,允許突發請求,只要有令牌就可以處理,支持一次拿3個令牌,4個令牌;漏桶限制的是常量流出速率,即流出速率是一個固定常量值,比如都是1的速率流出,而不能一次是1,下次又是2,從而平滑突發流入速率;

  • 令牌桶允許一定程度的突發,而漏桶主要目的是平滑流出速率;

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 {
    // 根據字符串分不同的令牌桶, 每天自動清理緩存
    private static LoadingCache<String, RateLimiter> cachesRateLimiter = CacheBuilder.newBuilder()
            .maximumSize(1000)  //設置緩存個數
            /**
             * expireAfterWrite是在指定項在一定時間內沒有創建/覆蓋時,會移除該key,下次取的時候從loading中取
             * expireAfterAccess是指定項在一定時間內沒有讀寫,會移除該key,下次取的時候從loading中取
             * refreshAfterWrite是在指定時間內沒有被創建/覆蓋,則指定時間過后,再次訪問時,會去刷新該緩存,在新值沒有到來之前,始終返回舊值
             * 跟expire的區別是,指定時間過后,expire是remove該key,下次訪問是同步去獲取返回新值;
             * 而refresh則是指定時間后,不會remove該key,下次訪問會觸發刷新,新值沒有回來時返回舊值
             */
            .expireAfterAccess(1, TimeUnit.HOURS)
            .build(new CacheLoader<String, RateLimiter>() {
                @Override
                public RateLimiter load(String key) throws Exception {
                    // 新的字符串初始化 (限流每秒2個令牌響應)
                    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.測試結果

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

其他

創建

RateLimiter提供了兩個工廠方法:

一個是平滑突發限流

RateLimiter r = RateLimiter.create(5); //項目啟動,直接允許5個令牌

一個是平滑預熱限流

RateLimiter r = RateLimiter.create(2, 3, TimeUnit.SECONDS); //項目啟動后3秒后才會到達設置的2個令牌

缺點

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

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

感謝各位的閱讀,以上就是“SpringBoot怎么使用RateLimiter通過AOP方式進行限流”的內容了,經過本文的學習后,相信大家對SpringBoot怎么使用RateLimiter通過AOP方式進行限流這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西丰县| 黑水县| 日喀则市| 上饶县| 静宁县| 南投县| 洛南县| 平乐县| 钟祥市| 朝阳区| 德格县| 容城县| 澄江县| 浦江县| 甘南县| 永兴县| 玛纳斯县| 大冶市| 图木舒克市| 临高县| 柳河县| 灵川县| 波密县| 周至县| 太保市| 门头沟区| 东至县| 涡阳县| 闽侯县| 温州市| 交口县| 塔城市| 中江县| 莆田市| 托克逊县| 绥江县| 鄂尔多斯市| 霞浦县| 图木舒克市| 永寿县| 通辽市|