流量速率管控
温馨提示
在这里,通过深入学习代码实现,您将系统地探索如何实现流量速率管控
功能的具体代码细节。
# 🍜 常用限流方式
计数器限流
:计数器是最简单的限流算法,它记录单位时间内通过的请求数,当达到设定的阈值时,后续的请求会被拒绝。简单易实现,但不够平滑,当达到阈值后,会立即拒绝所有请求,可能导致“突然死亡”的情况。适用于短期、突发性的流量控制。滑动窗口限流
:动窗口是对计数器的一个改进,它将时间窗口划分为多个小区间(例如 1 秒内的 10 个 100ms 的区间),每个区间都有一个计数器。随着时间的推移,窗口向前滑动,最早的区间被丢弃,新的区间加入。相对于简单的计数器,滑动窗口可以更平滑地处理流量,避免了“突然死亡”的情况。适用于对时间敏感、要求平滑控制的场景。漏桶限流
:漏桶算法将请求比作流入桶中的水,桶有一个固定的流出速度。当请求速率小于流出速度时,请求会被顺利处理;当请求速率超过流出速度时,多余的请求会被拒绝或缓存。漏桶算法强调了匀速处理请求,可以平滑突发流量。适用于希望系统稳定、不希望出现突发流量的情况。令牌桶限流
:令牌桶算法与漏桶算法相反,它有一个固定容量的桶,桶中预先放入了一定数量的令牌。每次请求到来时,会尝试从桶中取出一个令牌,如果成功则处理请求,否则拒绝。桶中的令牌以一定的速率增加。令牌桶算法允许在一段时间内突发地处理大量请求,只要桶中的令牌足够。适用于允许一定突发流量,但又有一定限制的场景。
# 🍝 令牌桶算法
# 🥩 导入相关依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.21.0</version>
</dependency>
# ☕ 配置和初始化 RedissonClient
/**
* @author 邓哈哈
* 2023/10/16 20:36
* Function: Redisson 配置
* Version 1.0
*/
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
@Data
public class RedissionConfig {
private String host;
private String port;
private String password;
private Integer database;
@Bean
public RedissonClient redissonClient() {
// 1. 创建配置
Config config = new Config();
String redisAddress = String.format("redis://%s:%s", host, port);
// 使用单个Redis,没有开集群 useClusterServers() 设置地址和使用库
config.useSingleServer().setAddress(redisAddress).setDatabase(database).setPassword(password);
// 2. 创建实例
return Redisson.create(config);
}
}
以上这段逻辑是一个 Spring Boot 的配置类,用于配置和初始化 RedissonClient,它是 Redisson 库的一个核心接口,用于与 Redis 数据库进行交互。
# 🥡 基于 Redisson 的限流管理器实现
/**
* @author 邓哈哈
* 2023/10/10 22:23
* Function: 用户调用接口限流实现
* Version 1.0
*/
@Service
public class RedisLimiterManager {
@Resource
private RedissonClient redissonClient;
/**
* 限流实现
*
* @param key 识别用户的key
*/
public void doRateLimit(String key) {
// 创建限流器
RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
rateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS);
// 每当一个操作来了之后,请求一个令牌
boolean canOp = rateLimiter.tryAcquire(1);
// 超出发放令牌数目,请求过于频繁
ThrowUtils.throwIf(!canOp, ErrorCode.TOO_MANY_REQUEST);
}
}
这段代码是一个基于 Redisson 的限流管理器
实现,它利用 Redisson 提供的分布式限流功能来限制用户对特定接口的调用频率。
RedisLimiterManager 类中的 doRateLimit 方法接受一个 key 参数,该参数用于识别不同的用户或请求。该方法首先通过 redissonClient.getRateLimiter(key)获取一个与给定 key 相关联的 RRateLimiter 实例。然后,它使用 trySetRate 方法设置限流规则,这里设置为每秒最多允许 2 个请求(即每秒发放 2 个令牌)。
接下来,每当有请求到来时,tryAcquire(1)方法会被调用以尝试获取一个令牌。如果当前请求的速率超过了设定的
限流规则
(即每秒超过 2 个请求),则 tryAcquire 方法将返回 false,表示没有获取到令牌。此时,ThrowUtils.throwIf 方法会抛出一个异常(这里假设是 ErrorCode.TOO_MANY_REQUEST),表明请求过于频繁,需要进行限流处理。
总之,这段代码的主要目的是通过 Redisson 提供的分布式限流功能
,对用户调用接口的频率进行限制,以防止接口被过度访问或滥用。