• Springboot框架中使用 Redis + Lua 脚本进行限流功能


    Springboot框架中使用 Redis + Lua 脚本进行限流功能

    限流是一种用于控制系统资源利用率或确保服务质量的策略。在Web应用中,限流通常用于控制接口请求的频率,防止过多的请求导致系统负载过大或者防止恶意攻击。

    什么是限流?

    限流是一种通过限制请求的速率或数量,以防止系统被过度使用或滥用的策略。它可以帮助维护系统的稳定性、可用性和性能。限流的目标通常是平滑请求流量,防止短时间内过多的请求对系统造成冲击。

    为什么需要限流?

    1. 保护系统稳定性: 防止过多的请求导致系统资源耗尽,例如数据库连接、线程池等,从而保护系统的稳定性。

    2. 防止恶意攻击: 限制请求频率可以防止恶意攻击,例如暴力破解、DDoS攻击等。

    3. 保障服务质量: 避免因过多请求而导致的服务质量下降,确保正常用户的良好体验。

    如何实现限流?

    在Spring Boot中,结合Redis和Lua脚本是一种常见的实现方式。具体步骤如下:

    1. 选择合适的Key: 限流通常需要根据请求的特性选择合适的Key,例如用户ID、接口路径等,以确保限流的粒度和准确性。

    2. 编写Lua脚本: 使用Lua脚本可以在Redis中原子性地执行限流逻辑。脚本中通常包含对计数器的增加、过期时间的设置和判断是否超过限制的逻辑。

    3. 在Spring Boot中使用RedisTemplate: 利用Spring Boot的RedisTemplate来执行Lua脚本,确保在多线程环境下的原子性操作。

    4. 集成到业务代码中: 在需要进行限流的地方调用限流工具,根据返回结果决定是否继续处理业务逻辑或者拒绝请求。

    在Spring Boot框架中,使用Redis和Lua脚本进行限流功能是一种常见的做法,可以有效地控制系统的请求流量,防止突发的大量请求对系统造成压力。下面是一个简单的Spring Boot项目中使用Redis和Lua脚本进行限流的流程说明和示例代码:

    步骤1: 添加依赖

    首先,在pom.xml文件中添加Redis和Spring Boot的相关依赖:

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframework.bootgroupId>
    4. <artifactId>spring-boot-starter-data-redisartifactId>
    5. dependency>
    6. dependencies>

    步骤2: 配置Redis连接

    application.properties文件中配置Redis连接信息:

    1. spring.redis.host=localhost
    2. spring.redis.port=6379

    步骤3: 编写限流工具类

    创建一个RateLimiter类,用于执行Lua脚本进行限流操作:

    1. import org.springframework.data.redis.core.RedisTemplate;
    2. import org.springframework.data.redis.core.script.DefaultRedisScript;
    3. import org.springframework.data.redis.core.script.RedisScript;
    4. import org.springframework.stereotype.Component;
    5. import java.util.Collections;
    6. @Component
    7. public class RateLimiter {
    8. private final RedisTemplate redisTemplate;
    9. public RateLimiter(RedisTemplate redisTemplate) {
    10. this.redisTemplate = redisTemplate;
    11. }
    12. public boolean allowRequest(String key, int maxRequests, long timeWindowSeconds) {
    13. String luaScript = "local current = redis.call('incr', KEYS[1])\n" +
    14. "if tonumber(current) == 1 then\n" +
    15. " redis.call('expire', KEYS[1], ARGV[1])\n" +
    16. "end\n" +
    17. "return tonumber(current) <= tonumber(ARGV[2])";
    18. RedisScript redisScript = new DefaultRedisScript<>(luaScript, Boolean.class);
    19. Boolean result = redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(timeWindowSeconds), String.valueOf(maxRequests));
    20. if (result == null) {
    21. // 处理脚本执行失败的情况
    22. return false;
    23. }
    24. return result;
    25. }
    26. }

    步骤4: 在Controller中使用限流

    在需要进行限流的Controller中,注入RateLimiter并使用它进行限流:

    1. import org.springframework.beans.factory.annotation.Autowired;
    2. import org.springframework.web.bind.annotation.GetMapping;
    3. import org.springframework.web.bind.annotation.RequestMapping;
    4. import org.springframework.web.bind.annotation.RestController;
    5. @RestController
    6. @RequestMapping("/api")
    7. public class ApiController {
    8. @Autowired
    9. private RateLimiter rateLimiter;
    10. @GetMapping("/limitedEndpoint")
    11. public String limitedEndpoint() {
    12. String key = "user:1:apiLimitedKey"; // 根据实际情况生成唯一的key,可以使用用户ID等信息
    13. int maxRequests = 10; // 允许的最大请求数
    14. long timeWindowSeconds = 60; // 时间窗口大小,单位秒
    15. if (rateLimiter.allowRequest(key, maxRequests, timeWindowSeconds)) {
    16. // 允许请求的业务逻辑
    17. return "Request allowed!";
    18. } else {
    19. // 请求限流的业务逻辑
    20. return "Request blocked due to rate limiting!";
    21. }
    22. }
    23. }

    在上述示例中,limitedEndpoint是一个受限制的接口,通过RateLimiter类进行限流。根据实际需要,可以根据不同的接口、用户等生成不同的key来进行限流。在RateLimiter类中,通过Lua脚本来原子性地执行限流逻辑,确保在多线程环境下的正确性。

    示例中完整代码,可以从下面网址获取:

    https://gitee.com/jlearning/wechatdemo.git

    https://github.com/icoderoad/wxdemo.git

  • 相关阅读:
    【光学】基于Matlab模拟光流场
    O2OA(翱途)常见知识之 mysql 数据库备份
    机器学习实战:用efficientdet训练自己的数据集
    【LeetCode】IPO(使用贪心求解)
    Cocos Creator3.8 项目实战(四)巧用九宫格图像拉伸
    Java解析MDB(上)-纯JDBC解析非空间数据
    技术干货|昇思MindSpore可变序列长度的动态Transformer已发布!
    小程序实现图片上传、数量配置、预览、删除功能的开发指南
    【Linux网络编程】网络编程初体验
    微信小程序 | 微信公众平台SpringBoot开发实例 │ 开发一个简易的个人微信公众号
  • 原文地址:https://blog.csdn.net/qq_30895747/article/details/134491439