MySQL, Oracle, Linux, 软件架构及大数据技术知识分享平台

网站首页 > 精选文章 / 正文

接口也会累着!Spring Boot + Redis 实现接口限流和防刷

2024-12-03 15:23 huorong 精选文章 7 ℃ 0 评论

越来越多的应用被部署到了云端,并在云端被高并发的访问。在这样的环境下,限流和防刷是非常重要的,因为如果不做好限流和防刷,那么很容易就会因为访问量过大而导致应用崩溃。在本文中,我们将会介绍如何使用Spring Boot和Redis来实现访问限流和接口防刷。篇幅有点长,但是满满的干活,大家地铁上慢慢看!!!

什么是限流和防刷?

在介绍如何使用Spring Boot和Redis实现限流和防刷之前,我们先来了解一下什么是限流和防刷。

限流,顾名思义,就是限制流量,也就是限制同一时间内能够访问某个接口的请求数量。通过限流,我们可以保证系统的稳定性,避免因为访问量过大而导致系统宕机的情况发生。

防刷,是指防止恶意请求,比如恶意爬虫、恶意攻击等。如果系统没有做好防刷,那么恶意请求很容易就会把系统压垮,因此防刷也是非常重要的一项工作。

Spring Boot和Redis

在介绍如何使用Spring Boot和Redis实现限流和防刷之前,我们先来了解一下什么是Spring Boot和Redis。

Spring Boot是一个开源的Java框架,它可以帮助我们快速搭建基于Spring的应用程序,减少了我们的开发时间和成本,同时提高了应用程序的可维护性。

Redis是一个高性能的键值存储系统,它支持多种数据结构,比如字符串、哈希表、列表等等。Redis可以用于缓存、消息队列、计数器等多种用途。

实现限流

接下来,我们将会介绍如何使用Spring Boot和Redis来实现限流。

在Redis中,我们可以使用令牌桶算法来实现限流。令牌桶算法的基本思想是,我们有一个固定容量的桶,以固定的速率往里面放入令牌,每当有一个请求需要访问系统时,就需要从桶中取出一个令牌,如果桶中没有令牌了,那么就需要等待,直到桶中有令牌为止。

首先,我们需要在pom.xml中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

接下来,我们需要在Redis中设置一个哈希表,用来存储每个接口的访问次数和访问时间。其中,哈希表的键是接口的路径,值是一个列表,列表中存储了接口的访问次数和访问时间。我们可以使用以下代码来初始化这个哈希表:

@Autowired
private RedisTemplate<String, Object> redisTemplate;

private static final String LIMIT_KEY_PREFIX = "limit:";

public void initLimitMap(String path, int limitCount, int limitTime) {
    String key = LIMIT_KEY_PREFIX + path;
    Map<String, Integer> map = new HashMap<>();
    map.put("count", 0);
    map.put("time", limitTime);
    redisTemplate.opsForHash().putAll(key, map);
    redisTemplate.expire(key, limitTime, TimeUnit.SECONDS);
}

在上面的代码中,我们使用了@Autowired注解来注入RedisTemplate实例。RedisTemplate是Spring提供的一个用于操作Redis的模板类,可以简化我们的Redis操作。

然后,我们可以使用initLimitMap方法来初始化每个接口的访问次数和访问时间。其中,path是接口的路径,limitCount是访问次数的限制,limitTime是访问时间的限制。

接下来,我们需要编写一个拦截器,在每个请求到达接口之前判断是否需要进行限流。在拦截器中,我们需要从Redis中获取当前接口的访问次数和访问时间,然后判断当前时间和上次访问时间的时间差是否超过访问时间的限制,如果超过了,则重置访问次数为1,否则增加访问次数。如果当前访问次数超过了访问次数的限制,则拒绝访问。

以下是一个简单的限流拦截器的代码:

public class LimitInterceptor extends HandlerInterceptorAdapter {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String path = request.getRequestURI();
        String key = LIMIT_KEY_PREFIX + path;
        BoundHashOperations<String, String, Integer> boundHashOps = redisTemplate.boundHashOps(key);

        int count = boundHashOps.get("count");
        int time = boundHashOps.get("time");
        long currentTime = System.currentTimeMillis();
        long lastTime = boundHashOps.get("lastTime");
        if (lastTime == 0) {
            lastTime = currentTime;
        }
        if (currentTime - lastTime > time * 1000) {
            count = 1;
        } else {
            count++;
        }
        boundHashOps.put("count", count);
        boundHashOps.put("lastTime", (int) currentTime);

        if (count > limitCount) {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write("请求太频繁");
            return false;
        }

        return true;
    }
}

在上面的代码中,我们使用了BoundHashOperations类来操作Redis中的哈希表。BoundHashOperations是RedisTemplate的一个子类,可以更加方便地操作Redis中的哈希表。

我们在拦截器中,首先获取当前接口的路径,并根据路径获取当前接口的限流信息。然后,我们判断当前时间和上次访问时间的时间差是否超过访问时间的限制,如果超过了,则重置访问次数为1,否则增加访问次数。最后,如果当前访问次数超过了访问次数的限制,则拒绝访问。

最后,我们需要在Spring Boot中注册我们的限流拦截器。我们可以使用以下代码来注册拦截器:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Autowired
    private LimitInterceptor limitInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(limitInterceptor);
    }
}

在上面的代码中,我们创建了一个WebConfig类,并使用@Configuration注解来声明该类是一个配置类。然后,我们实现了WebMvcConfigurer接口,并重写了其中的addInterceptors方法。在该方法中,我们将我们的限流拦截器注册到了拦截器列表中。

现在,我们可以使用上面的代码来实现接口的限流了。当有用户请求某个接口时,我们会根据用户的IP地址和接口的路径来判断是否需要进行限流,如果需要进行限流,则根据接口的限流配置来判断是否拒绝请求。同时,我们还可以使用Redis的持久化功能来保证我们的限流信息不会因为服务器重启而丢失。

在实际应用中,我们还可以根据业务需求来调整接口的限流策略。例如,对于一些特殊的接口,我们可以将限流次数设置得更高,以保证这些接口能够稳定运行。同时,我们还可以使用一些工具来监控接口的访问情况,以便及时调整限流策略。

总结

本文介绍了如何使用Spring Boot和Redis来实现接口的限流和防刷。通过使用Redis来存储限流信息,我们可以在分布式环境中方便地实现限流功能。同时,我们还可以根据业务需求来调整限流策略,以提高接口的可用性和稳定性。

需要注意的是,接口的限流和防刷只是保证接口能够正常运行的一种手段,我们还需要在代码中加入其他的安全措施,例如输入参数的校验、防SQL注入、防XSS攻击等。只有综合使用各种安全手段,才能有效地保障系统的安全性和稳定性。

下一篇内容我们来讨论一下接口防刷!

Tags:hashoperations

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言