Springboot使用redis进行api防刷限流过程详解

这篇文章主要介绍了Springboot使用redis进行api防刷限流过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

api限流的场景

限流的需求出现在许多常见的场景中

  • 秒杀活动,有人使用软件恶意刷单抢货,需要限流防止机器参与活动
  • 某api被各式各样系统广泛调用,严重消耗网络、内存等资源,需要合理限流
  • 淘宝获取ip所在城市接口、微信公众号识别微信用户等开发接口,免费提供给用户时需要限流,更具有实时性和准确性的接口需要付费。

api限流实战

首先我们编写注解类AccessLimit,使用注解方式在方法上限流更优雅更方便!三个参数分别代表有效时间、最大访问次数、是否需要登录,可以理解为 seconds 内最多访问 maxCount 次。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AccessLimit {
  int seconds();
  int maxCount();
  boolean needLogin() default true;
}

限流的思路

  • 通过路径:ip的作为key,访问次数为value的方式对某一用户的某一请求进行唯一标识
  • 每次访问的时候判断key是否存在,是否count超过了限制的访问次数
  • 若访问超出限制,则应response返回msg:请求过于频繁给前端予以展示
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class AccessLimtInterceptor implements HandlerInterceptor {

  @Autowired
  private RedisService redisService;

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    if (handler instanceof HandlerMethod) {
      HandlerMethod hm = (HandlerMethod) handler;
      AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
      if (null == accessLimit) {
        return true;
      }
      int seconds = accessLimit.seconds();
      int maxCount = accessLimit.maxCount();
      boolean needLogin = accessLimit.needLogin();

      if (needLogin) {
        //判断是否登录
      }

      String key = request.getContextPath() + ":" + request.getServletPath() + ":" + ip ;

      Integer count = redisService.get(key);

      if (null == count || -1 == count) {
        redisService.set(key, 1);
        redisService.expire(seconds);
        return true;
      }

      if (count < maxCount) {
        redisService.inCr(key);
        return true;
      }

      if (count >= maxCount) {
//        response 返回 json 请求过于频繁请稍后再试
        return false;
      }
    }

    return true;
  }
}

注册拦截器并配置拦截路径和不拦截路径

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// extends WebMvcConfigurerAdapter 已经废弃,java 8开始直接继承就可以
@Configuration
public class IntercepterConfig implements WebMvcConfigurer {
  @Autowired
  private AccessLimtInterceptor accessLimtInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(accessLimtInterceptor)
        .addPathPatterns("/拦截路径")
        .excludePathPatterns("/不被拦截路径 通常为登录注册或者首页");
  }
}

在Controller层的方法上直接可以使用注解@AccessLimit

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("test")
public class TestControler {

  @GetMapping("accessLimit")
  @AccessLimit(seconds = 3, maxCount = 10)
  public String testAccessLimit() {
    //xxxx
    return "";
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • springBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> 2.编写一个CacheService接口,使用redisCach

  • 基于springboot和redis实现单点登录

    本文实例为大家分享了基于springboot和redis实现单点登录的具体代码,供大家参考,具体内容如下 1.具体的加密和解密方法 package com.example.demo.util; import com.google.common.base.Strings; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.Cipher; import javax.crypto.KeyG

  • SpringBoot 整合 Lettuce Redis的实现方法

    SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程 Spring Boot 除了支持常见的ORM框架外,更是对常用的中间件提供了非常好封装,随着Spring Boot2.x的到来,支持的组件越来越丰富,也越来越成熟,其中对Redis的支持不仅仅是丰富了它的API,更是替换掉底层Jedis的依赖,取而代之换成了Le

  • SpringBoot Redis配置Fastjson进行序列化和反序列化实现

    FastJson是阿里开源的一个高性能的JSON框架,FastJson数据处理速度快,无论序列化(把JavaBean对象转化成Json格式的字符串)和反序列化(把JSON格式的字符串转化为Java Bean对象),都是当之无愧的fast:功能强大(支持普通JDK类,包括javaBean, Collection, Date 或者enum):零依赖(没有依赖其他的任何类库). 1.写一个自定义序列化类 /** * 自定义序列化类 * @param <T> */ public class FastJ

  • springboot整合redis集群过程解析

    简介 在springboot使用搭建好的redis集群 添加redis和连接池依赖 <!--redis连接池 start--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!--redis连接池 end--> <!--redis start-

  • SpringBoot+Redis执行lua脚本的方法步骤

    1.背景 有时候,我们需要一次性操作多个 Redis 命令,但是 这样的多个操作不具备原子性,而且 Redis 的事务也不够强大,不支持事务的回滚,还无法实现命令之间的逻辑关系计算.所以,一般在开发中,我们会利用 lua 脚本来实现 Redis 的事务. 2.lua 脚本 Redis 中使用 lua 脚本,我们需要注意的是,从 Redis 2.6.0后才支持 lua 脚本的执行. 使用 lua 脚本的好处: 原子操作:lua脚本是作为一个整体执行的,所以中间不会被其他命令插入. 减少网络开销:可

  • springboot配置redis过程详解

    在springboot中,默认继承好了一套完好的redis包,可以直接使用,但是如果使用中出了错不容易找到错误的原因,因此这里使用自己配置的redis: 需要使用的三个主要jar包: <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>

  • SpringBoot集成Redisson实现分布式锁的方法示例

    上篇 <SpringBoot 集成 redis 分布式锁优化>对死锁的问题进行了优化,今天介绍的是 redis 官方推荐使用的 Redisson ,Redisson 架设在 redis 基础上的 Java 驻内存数据网格(In-Memory Data Grid),基于NIO的 Netty 框架上,利用了 redis 键值数据库.功能非常强大,解决了很多分布式架构中的问题. Github的wiki地址: https://github.com/redisson/redisson/wiki 官方文档

  • Springboot使用redis进行api防刷限流过程详解

    这篇文章主要介绍了Springboot使用redis进行api防刷限流过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 api限流的场景 限流的需求出现在许多常见的场景中 秒杀活动,有人使用软件恶意刷单抢货,需要限流防止机器参与活动 某api被各式各样系统广泛调用,严重消耗网络.内存等资源,需要合理限流 淘宝获取ip所在城市接口.微信公众号识别微信用户等开发接口,免费提供给用户时需要限流,更具有实时性和准确性的接口需要付费. api限流实

  • Java微服务Filter过滤器集成Sentinel实现网关限流过程详解

    目录 Gateway-过滤器Filter 局部路由过滤器 使用局部过滤器 全局过滤器 使用全局过滤器 集成Sentinel实现网关限流 网关限流 API分组限流 Gateway-过滤器Filter 过滤器就是在请求的传递过程中,对请求和响应做一些手脚. 在Gateway中, Filter的生命周期只有两个:“pre”和“post”". .PRE:这种过滤器在请求被路由之前调用.我们可利用这种过滤器实现身份验证.在集群中选择请求的微服务.记录调试信息等. .POST:这种过滤器在路由到微服务以后执

  • 基于Redis zSet实现滑动窗口对短信进行防刷限流的问题

    前言 主要针对目前线上短信被脚本恶意盗刷的情况,用Redis实现滑动窗口限流 public void checkCurrentWindowValue(String telNum) { String windowKey = CommonConstant.getNnSmsWindowKey(telNum); //获取当前时间戳 long currentTime = System.currentTimeMillis(); //1小时,默认只能发5次,参数smsWindowMax做成可配置项,配置到Na

  • SpringBoot使用swagger生成api接口文档的方法详解

    目录 前言 具体例子 maven配置 项目application.yml配置 springApplication添加swagger注解 在控制层添加swagger注解 前言 在之前的文章中,使用mybatis-plus生成了对应的包,在此基础上,我们针对项目的api接口,添加swagger配置和注解,生成swagger接口文档 具体可以查看本站spring boot系列文章: spring boot项目使用mybatis-plus代码生成实例 具体例子 maven配置 在使用之前,我们需要添加s

  • Go语言框架快速集成限流中间件详解

    目录 前言 分布式版 简介 算法 实现 注意 单机版 简介 算法 实现 结语 前言 在我们的日常开发中, 常用的中间件有很多, 今天来讲一下怎么集成限流中间件, 它可以很好地用限制并发访问数来保护系统服务, 避免系统服务崩溃, 资源占用过大甚至服务器崩溃进而影响到其他应用! 分布式版 简介 通常我们的服务会同时存在多个进程, 也就是负载来保证服务的性能和稳定性, 那么就需要走一个统一的限流, 这个时候就需要借助我们的老朋友-redis, 来进行分布式限流; 算法 漏桶算法 即一个水桶, 进水(接

  • Spring-boot 2.3.x源码基于Gradle编译过程详解

    spring Boot源码编译 1. git上下拉最新版的spring Boot 下载:git clone git@github.com:spring-projects/spring-boot.git,建议下载release版本,不会出现奇奇怪怪的错误 2.修改下载源, gradle\wrapper中的配置文件 gradle-wrapper.properties distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists #d

  • React SSR 中的限流案例详解

    目录 为什么要限流 令牌桶算法 当对 React 应用进行页面加载或 SEO 优化时,我们一般绕不开 React SSR.但 React SSR 毕竟涉及到了服务端,有很多服务端特有的问题需要考虑,而限流就是其中之一. 所谓限流,就是当我们的服务资源有限.处理能力有限时,通过对请求或并发数进行限制从而保障系统正常运行的一种策略.本文会通过一个简单的案例来说明,为什么服务端需要进行限流. 为什么要限流 如下所示是一个简单的 nodejs 服务端项目: const express = require

  • Nginx源码研究之nginx限流模块详解

    高并发系统有三把利器:缓存.降级和限流: 限流的目的是通过对并发访问/请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务(定向到错误页).排队等待(秒杀).降级(返回兜底数据或默认数据): 高并发系统常见的限流有:限制总并发数(数据库连接池).限制瞬时并发数(如nginx的limit_conn模块,用来限制瞬时并发连接数).限制时间窗口内的平均速率(nginx的limit_req模块,用来限制每秒的平均速率): 另外还可以根据网络连接数.网络流量.CPU或内存负载等来限流. 1.限流算法 最

  • java秒杀之redis限流操作详解

    最近写到了一个秒杀的功能模块,为了保证高并发情况下不会宕机,要从多方面去考虑,当前的限流操作只是其中的一个方面,具体操作如下. 导入所需依赖 <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.targ

  • Golang官方限流器库实现限流示例详解

    目录 前言 例子 实现 小结 前言 在翻Golang官方库的过程中,发现一个有趣的库golang.org/x/time ,里面只有一个类rate,研究了一下发现它是一个限流器,实现了很多的功能,当然它的核心原理并不复杂,也就是令牌桶算法. 令牌桶算法的原理是:令牌桶会不断地把令牌添加到桶里,而请求会从桶中获取令牌,只有拥有令牌地请求才能被接受.因为桶中可以提前保留一些令牌,所以它允许一定地突发流量通过. 例子 下面是限流算法常见的写法,首先判断是否有令牌,如果有就通过,否则直接失败. packa

随机推荐