wang-hao-jie
2022-01-07 0f2202dfcea3309c1b0e7515f6db5fbdc83d51d1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package cn.exrick.xboot.core.common.limit;
 
import cn.exrick.xboot.core.common.constant.CommonConstant;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import java.util.concurrent.TimeUnit;
 
/**
 * 令牌桶算法限流
 * @author Exrick
 */
@Slf4j
@Component
public class RedisRaterLimiter {
 
    @Autowired
    private RedissonClient redisson;
 
    private RateLimiter guavaRateLimiter = RateLimiter.create(Double.MAX_VALUE);
 
    /**
     * 基于Redis令牌桶算法
     * @param name         限流标识(限流点)
     * @param rate         限制的数量 速率
     * @param rateInterval 单位时间内(毫秒)
     * @return
     */
    public Boolean acquireByRedis(String name, Long rate, Long rateInterval) {
 
        boolean getToken;
        try {
            RRateLimiter rateLimiter = redisson.getRateLimiter(CommonConstant.LIMIT_PRE + name);
            rateLimiter.trySetRate(RateType.OVERALL, rate, rateInterval, RateIntervalUnit.MILLISECONDS);
            getToken = rateLimiter.tryAcquire();
            rateLimiter.expireAsync(rateInterval * 2, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            getToken = true;
        }
        return getToken;
    }
 
    /**
     * 基于内存令牌桶算法
     * @param permitsPerSecond 1秒内限制的数量(QPS)
     * @return
     */
    public Boolean acquireByGuava(Double permitsPerSecond) {
 
        guavaRateLimiter.setRate(permitsPerSecond);
 
        boolean getToken = guavaRateLimiter.tryAcquire();
 
        return getToken;
    }
}