实现 Spring Boot Redis 滑动窗口限流
在开发过程中,我们常常需要对请求进行限流,以防止服务器过载。Redis 滑动窗口是一种常用的限流策略。本文将带你一步步实现 Spring Boot 项目中的 Redis 滑动窗口限流,适合初学者。
流程概述
以下是实现 Redis 滑动窗口的步骤:
步骤 | 描述 | 需要的代码 |
---|---|---|
1 | 创建 Spring Boot 项目 | 使用 Spring Initializr 工具 |
2 | 添加 Redis 依赖 | pom.xml 中添加 Redis 依赖 |
3 | 配置 Redis | application.yml 或 application.properties |
4 | 实现滑动窗口算法 | 编写 RedisService 类 |
5 | 编写拦截器或过滤器实现限流 | 创建 RateLimitInterceptor 类 |
6 | 测试滑动窗口限流 | 编写测试用例 |
详细步骤
1. 创建 Spring Boot 项目
首先,你可以使用 [Spring Initializr]( 创建一个新的 Spring Boot 项目,选择 Web 和 Redis 依赖。
2. 添加 Redis 依赖
在 pom.xml
中添加 Redis 相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3. 配置 Redis
在 application.yml
中配置 Redis 连接信息:
spring:
redis:
host: localhost
port: 6379
4. 实现滑动窗口算法
创建一个 RedisService
类来处理滑动窗口的逻辑。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 限流方法
public boolean tryAcquire(String key, int limit, long windowSize) {
long currentTime = System.currentTimeMillis();
long timeWindowStart = currentTime - windowSize;
// 添加当前请求时间戳
redisTemplate.opsForList().rightPush(key, currentTime);
// 删除超出时间窗口的请求
redisTemplate.opsForList().remove(key, 0, timeWindowStart);
Long count = redisTemplate.opsForList().size(key);
// 设置过期时间
redisTemplate.expire(key, windowSize, TimeUnit.MILLISECONDS);
// 判断是否超过限制
return count <= limit;
}
}
tryAcquire
方法用来尝试获取请求的许可。rightPush
将当前请求的时间戳存入 Redis 列表。remove
方法删除超出时间窗口的请求。size
方法获取当前请求数量,判断是否超出限制。
5. 编写拦截器或过滤器实现限流
创建 RateLimitInterceptor
类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class RateLimitInterceptor implements HandlerInterceptor {
@Autowired
private RedisService redisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String key = request.getRequestURI();
int limit = 5; // 每个窗口的请求限制
long windowSize = 60000; // 1分钟的时间窗口
if (!redisService.tryAcquire(key, limit, windowSize)) {
response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
return false;
}
return true;
}
}
preHandle
方法用于拦截 HTTP 请求并进行限流控制。
6. 测试滑动窗口限流
你可以编写 JUnit 测试用例来验证限流功能是否正常。
流程图 & 类图
流程图
journey
title 滑动窗口限流流程
section 请求发送
用户发送请求: 5: user
section 请求处理
处理请求: 4: app
检查请求限制: 4: app
超出阈值, 返回 429: 5: app
类图
classDiagram
class RedisService {
+boolean tryAcquire(String key, int limit, long windowSize)
}
class RateLimitInterceptor {
+boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
}
class App {
<<application>>
}
App --> RedisService
App --> RateLimitInterceptor
结尾
通过上述步骤,你已经成功地实现了 Spring Boot 中的 Redis 滑动窗口限流。掌握了这个过程后,你可以根据自己的业务需求进行更复杂的定制。希望你能在后续的开发中灵活应用这一限流机制,提高系统的稳定性!如有疑问,欢迎提问。