当前位置: 首页 > article >正文

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的相关依赖:

<dependencies>
    <!-- Spring Boot Starter Data Redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>

步骤2: 配置Redis连接

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

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

步骤3: 编写限流工具类

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

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import java.util.Collections;

@Component
public class RateLimiter {

    private final RedisTemplate<String, Object> redisTemplate;

    public RateLimiter(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public boolean allowRequest(String key, int maxRequests, long timeWindowSeconds) {
        String luaScript = "local current = redis.call('incr', KEYS[1])\n" +
                "if tonumber(current) == 1 then\n" +
                "    redis.call('expire', KEYS[1], ARGV[1])\n" +
                "end\n" +
                "return tonumber(current) <= tonumber(ARGV[2])";

        RedisScript<Boolean> redisScript = new DefaultRedisScript<>(luaScript, Boolean.class);

        Boolean result = redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(timeWindowSeconds), String.valueOf(maxRequests));

        if (result == null) {
            // 处理脚本执行失败的情况
            return false;
        }

        return result;
    }
}

步骤4: 在Controller中使用限流

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class ApiController {

    @Autowired
    private RateLimiter rateLimiter;

    @GetMapping("/limitedEndpoint")
    public String limitedEndpoint() {
        String key = "user:1:apiLimitedKey"; // 根据实际情况生成唯一的key,可以使用用户ID等信息
        int maxRequests = 10; // 允许的最大请求数
        long timeWindowSeconds = 60; // 时间窗口大小,单位秒

        if (rateLimiter.allowRequest(key, maxRequests, timeWindowSeconds)) {
            // 允许请求的业务逻辑
            return "Request allowed!";
        } else {
            // 请求限流的业务逻辑
            return "Request blocked due to rate limiting!";
        }
    }
}

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

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

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

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


http://www.kler.cn/news/135678.html

相关文章:

  • Flutter最新稳定版3.16 新特性介绍
  • 达尔优EK87键盘说明书
  • sapjco3.dll has version “721.619“, but required is at least version “721.913“
  • 【Spring boot】RedisTemplate中String、Hash、List设置过期时间
  • 【Java并发编程九】同步控制
  • Redis-核心数据结构
  • 【C/PTA】数组进阶练习(一)
  • 4.Spring IoC 的实现机制是什么?
  • Bean实例化的基本流程
  • 色彩的基础知识——适用于camera tuning
  • Failed to execute org.scala-tools:maven-scala-plugin:2.15.2解决
  • 携带二进制文件的软件恢复方法
  • ZC序列理论学习及仿真
  • 【人工智能时代的刑法体系与责任主体概述】
  • 数据结构:枚举
  • 图片降噪软件 Topaz DeNoise AI mac中文版功能
  • Chrome添加扩展程序
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • 重要功能丨支持1688API接口接入一键跨境铺货及采购,解决跨境卖家货源烦恼!
  • 【数据结构初阶】双链表
  • 多因素方差分析(Multi-way Analysis of Variance) R实现
  • 栈和队列知识点+例题
  • 中国农业开启加速度,龙江农业迎来黄金期
  • 二阶段提交
  • thonny的汉字编码是UTF-8,如何才能转为GB2312?
  • LeetCode - 622. 设计循环队列(C语言,顺序存储结构,配图)
  • 逻辑漏洞(越权)
  • MySQL 的执行原理(五)
  • AI 游戏工具收集
  • 设计模式(二)-创建者模式(1)-单例模式