为什么要限流

系统在设计的时候,我们会有一个系统的预估容量,长时间超过系统能承受的TPS/QPS阈值,系统有可能会被压垮,最终导致整个服务不可用。为了避免这种情况,我们就需要对接口请求进行限流。

所以,我们可以通过对并发访问请求进行限速或者一个时间窗口内的的请求数量进行限速来保护系统或避免不必要的资源浪费,一旦达到限制速率则可以拒绝服务、排队或等待。 

 

限流背景

系统有一个获取手机短信验证码的接口,因为是开放接口,所以为了避免用户不断的发送请求获取验证码,防止恶意刷接口的情况发生,于是用最简单的计数器方式做了限流,限制每个IP每分钟只能请求一次,然后其他每个手机号的时间窗口限制则是通过业务逻辑进行判断。一般一些接口访问量比较大的,可能会压垮系统的,则需要加入流量限制!如:秒杀等...

实现限流

1、引入依赖

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

2、自定义限流注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter
{
/**
* 限流key
*/
String key() default Constants.RATE_LIMIT_KEY; /**
* 限流时间,单位秒
*/
int time() default 60; /**
* 限流次数
*/
int count() default 100; /**
* 限流类型
*/
LimitType limitType() default LimitType.DEFAULT; /**
* 限流后返回的文字
*/
String limitMsg() default "访问过于频繁,请稍候再试";
}

3、限流切面

@Aspect
@Component
public class RateLimiterAspect { private final static Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); @Autowired
private RedisUtils redisUtils; @Before("@annotation(rateLimiter)")
public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable
{
int time = rateLimiter.time();
int count = rateLimiter.count();
long total = 1L; String combineKey = getCombineKey(rateLimiter, point);
try
{
if(redisUtils.hasKey(combineKey)){
total = redisUtils.incr(combineKey,1); //请求进来,对应的key加1
if(total > count)
throw new ServiceRuntimeException(rateLimiter.limitMsg());
}else{
redisUtils.set(combineKey,1,time); //初始化key
}
}
catch (ServiceRuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new ServiceRuntimeException("网络繁忙,请稍候再试");
}
} /**
* 获取限流key
* @param rateLimiter
* @param point
* @return
*/
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
{
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
if (rateLimiter.limitType() == LimitType.IP)
{
stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
}
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Class<?> targetClass = method.getDeclaringClass();
stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
return stringBuffer.toString();
} }

4、写一个简单的接口进行测试

@RestController
public class TestController { @RateLimiter(time = 60, count = 1, limitType = LimitType.IP, limitMsg = "一分钟内只能请求一次,请稍后重试")
@GetMapping("/hello")
public ResultMsg hello() {
return ResultMsg.success("Hello World!");
}
}

5、全局异常拦截

@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); /**
* 业务异常
*/
@ExceptionHandler(ServiceRuntimeException.class)
public ResultMsg handleServiceException(ServiceRuntimeException e, HttpServletRequest request)
{
return ResultMsg.error(e.getMessage());
} /**
* 系统异常
*/
@ExceptionHandler(Exception.class)
public ResultMsg handleException(Exception e, HttpServletRequest request)
{
return ResultMsg.error("系统异常");
} }

6、接口测试

1)第一次发送,正常返回结果

2)一分钟内第二次发送,返回错误,限流提示

好了,大功告成啦

还有其他的限流方式,如滑动窗口限流方式(比计数器更严谨)、令牌桶等...,有兴趣的小伙伴可以学习一下

附源码

https://gitee.com/jae_1995/ratelimiter

SpringBoot使用自定义注解+AOP+Redis实现接口限流的更多相关文章

  1. 服务限流 -- 自定义注解基于RateLimiter实现接口限流

    1. 令牌桶限流算法 令牌桶会以一个恒定的速率向固定容量大小桶中放入令牌,当有浏览来时取走一个或者多个令牌,当发生高并发情况下拿到令牌的执行业务逻辑,没有获取到令牌的就会丢弃获取服务降级处理,提示一个 ...

  2. 库存秒杀问题-redis解决方案- 接口限流

    <?php/** * Created by PhpStorm. * redis 销量超卖秒杀解决方案 * redis 文档:http://doc.redisfans.com/ * ab -n 1 ...

  3. spring中实现基于注解实现动态的接口限流防刷

    本文将介绍在spring项目中自定义注解,借助redis实现接口的限流 自定义注解类 import java.lang.annotation.ElementType; import java.lang ...

  4. Redis除了做缓存--Redis做消息队列/Redis做分布式锁/Redis做接口限流

    1.用Redis实现消息队列 用命令lpush入队,rpop出队 Long size = jedis.lpush("QueueName", message);//返回存放的数据条数 ...

  5. 【高并发】亿级流量场景下如何为HTTP接口限流?看完我懂了!!

    写在前面 在互联网应用中,高并发系统会面临一个重大的挑战,那就是大量流高并发访问,比如:天猫的双十一.京东618.秒杀.抢购促销等,这些都是典型的大流量高并发场景.关于秒杀,小伙伴们可以参见我的另一篇 ...

  6. SpringCloud微服务实战——搭建企业级开发框架(三十九):使用Redis分布式锁(Redisson)+自定义注解+AOP实现微服务重复请求控制

      通常我们可以在前端通过防抖和节流来解决短时间内请求重复提交的问题,如果因网络问题.Nginx重试机制.微服务Feign重试机制或者用户故意绕过前端防抖和节流设置,直接频繁发起请求,都会导致系统防重 ...

  7. ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存

    基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...

  8. Springboot+Redisson自定义注解一次解决重复提交问题(含源码)

    前言   项目中经常会出现重复提交的问题,而接口幂等性也一直以来是做任何项目都要关注的疑难点,网上可以查到非常多的方案,我归纳了几点如下:   1).数据库层面,对责任字段设置唯一索引,这是最直接有效 ...

  9. 基于注解的接口限流+统一session认证

    代码心得: 一个基本的做法:对于用户身份认证做到拦截器里,针对HandlerMethod进行统一拦截认证,根据方法上的注解标识,判别是否需要身份验证,并将查找出来的User实体存入ThreadLoca ...

随机推荐

  1. HashMap1.8常见面试问题

    1.hashmap转红黑树的时机: for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNod ...

  2. 期末人福音——用Python写个自动批改作业系统

    一.亮出效果 最近一些软件的搜题.智能批改类的功能要下线. 退1024步讲,要不要自己做一个自动批改的功能啊?万一哪天孩子要用呢! 昨晚我做了一个梦,梦见我实现了这个功能,如下图所示:功能简介:作对了 ...

  3. 贝壳自动化测试平台sosotest 学习记录

    手工测试VS自动化测试 用例执行: 手动执行 自动执行 是否需要些脚本: 需要 不需要 测试报告生成: 手动 自动 常见的测试技术 关键字驱动的测试框架 RobotFRamework 单元测试框架 自 ...

  4. 【docker专栏4】使用docker安装nginx提供web服务

    一般学习一项技术,会先用一个最简单的例子或最典型的例子来向大家讲解入门内容,所以此文为大家介绍使用docker安装nginx容器服务.从基础使用的角度来讲,此文几乎涵盖了docker最核心的内容:镜像 ...

  5. jsx/tsx使用cssModule和typescript-plugin-css-modules

    目录 1,前言 2,效果图 3,如何使用 3.1,安装 3.2,配置 4,示例 5,插件错误处理 5.1,错误触发原因 5.2,解决办法 1,前言 在vite/webpack搭建的项目中,不管是vue ...

  6. 题解 P1999【覆盖墙壁】

    数学题 令 \(A_n\) 为 \(2\times n\) 的墙壁放满块的方案数,考虑递推. 显然 \(A_0=1\),我们令对于 \(k<0\),\(A_k=0\) . 放直线型的块非常好递推 ...

  7. Nginx 目录结构、Nginx服务控制命令

    # Nginx目录结构 # 首先推荐一个查看目录结构的工具 tree # yum install -y tree # sudo apt-get install -y tree ubuntu # 查看n ...

  8. GitHub 主页美化设置教程

    GitHub profile设置教程 早些时候逛GitHub,就发现别人的主页特别的精美,当时没有空研究,前几天得空给安排了一下 先看一下成品 贴一个github上一个男人的主页 下面这个是我的 果然 ...

  9. 美女 Committer 手把手教你部署 Apache DolphinScheduler 单机版

    还在为如何部署Apache DolphinScheduler 发愁么?自上篇<美女 Committer 手把手教你使用海豚调度>的视频发布后,受到社区伙伴们的热烈欢迎.但个别小伙伴在部署这 ...

  10. 【喜讯】Apache DolphinScheduler 荣获 “2020 年度十大开源新锐项目”

    经 10000+ 开发者公开票选,20+专家评审. 10+ 主编团打分,历经数月打磨,11 月 19 日,由InfoQ 发起并组织的[2020中国技术力量年度榜单评选]结果正式揭晓. 2020 年度十 ...