- 当开发人员开发一个接口暴露给外部,为了防止接口调用过于频繁会进行一些限流操作
目前在代码中发现有部分代码的限流操作为创建一个集合,然后在调用接口的时候生成一个UUID然后保存到集合中,判断当前集合的大小,如果超过限制的大小则返回异常
代码如下:
该段代码如果是在多台服务器的时候,只是限流的是当前服务器,没有实现分布式控制的逻辑
- 针对如上问题可以使用redis解决该问题,并且redis也提供了对应的工具包
- 基于Redis的数据结构zset
实现思路
-
-
- 判断zset中根据时间区间判断是否包含多少个请求
- 如果超过限制则返回,如果没超过限制,生成一个UUID保存到zset中
- 删除上一个时间段保存的请求,防止zset集合过大
-
代码示例
-
- 基于redis的令牌桶机制进行实现(leftPop+ rightPush)
实现思路
-
-
- 在一定时间段内给reids中放固定数量的数据
- 每次请求过来之后从集合中获取一个令牌,获取到则通过,获取不到则限流
-
@Scheduled(fixedDelay = 10_000,initialDelay = 0)
public void setIntervalTimeTask(){
redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());
}
public Response limitFlow(Long id){
Object result = redisTemplate.opsForList().leftPop("limit_list");
if(result == null){
return Response.ok("当前令牌桶中无令牌");
}
return Response.ok(articleDescription2);
}