Springboot接口限流

写在前面

在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流
缓存, 缓存的目的是提升系统访问速度和增大系统处理容量
降级, 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题解决后再打开
限流, 限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理
限流的需求出现在许多常见的场景中
•秒杀活动,有人使用软件恶意刷单抢货,需要限流防止机器参与活动
•某api被各式各样系统广泛调用,严重消耗网络、内存等资源,需要合理限流

实际情况

最近监控到公司服务器内存持续高占比,造成应用卡顿,经过分析日志发现是恶意的频繁的请求造成的。互联网公司工作,很难避免这种情况。
排查发现程序的所有接口都没有进行任何防护,相当于在裸奔,于是对接口进行了鉴权和加密,问题得到了解决,没有再发现恶意的请求。但是经过一段时间过后,产品提出2.0版本,用户不需要登录也可以浏览很多数据,放开了大部分需要鉴权的接口,那么问题来了,程序相当于开始重新裸奔,如何保证服务器的安全不因为恶意的频繁的请求而宕机成为了新的问题。
笔者采用了接口限流的方式,总体思路:结合redis控制单位时间内相同ip访问同一个接口的次数,将恶意的请求拦截在系统的上游。
1.自定义一个注解,这样可以灵活的控制每个接口与访问限制次数
2.定义切面范围,结合redis记录每个Ip对每个接口的单位时间的访问次数
3.在需要拦截的接口中判断用户是否在单位时间内频繁调起请求
一顿分析猛如虎,不是代码都是耍流氓。

代码如下:

package com.yn.ynmanage.aop.impl;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import java.lang.annotation.*;


/**
 * @author Chris he
 * @date 2020年07月17日 下午2:19:05
 * 自定义注解限制访问时间长度,最多访问次数
 */

@Retention(RetentionPolicy.RUNTIME)//注解的保留位置
@Target(ElementType.METHOD)//注解的作用目标
@Documented//说明该注解将被包含在javadoc中
@Order(Ordered.HIGHEST_PRECEDENCE)最高优先级

public @interface RequestTimes {
   
  //单位时间允许访问次数 - - -默认值是3
  int count() default 3;

  //设置单位时间为1秒钟 - - -即默认值1秒钟,1000 为毫秒。
  long time() default  1000;

}


import com.yn.ynmanage.security.JWTUtils;
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Spring Boot 中,我们可以使用 AOP(面向切面编程)和拦截器的方式来实现接口限流。以下是一个简单的实现方式: 1. 引入 Guava 库,它包含了令牌桶算法和漏斗算法的实现。 2. 定义一个注解 `@RateLimit`,用来标记需要进行限流接口。 ```java @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RateLimit { int value() default 100; // 默认每秒限制100个请求 } ``` 3. 定义一个切面 `RateLimitAspect`,在接口被调用时进行限流检查。 ```java @Aspect @Component public class RateLimitAspect { private final RateLimiter rateLimiter = RateLimiter.create(100.0); // 每秒100个请求 @Around("@annotation(rateLimit)") public Object limit(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable { if (rateLimiter.tryAcquire(rateLimit.value(), TimeUnit.MILLISECONDS)) { return joinPoint.proceed(); } else { throw new RuntimeException("接口限流,请稍后再试!"); } } } ``` 4. 在接口方法上添加 `@RateLimit` 注解,指定每秒允许的请求个数。 ```java @RestController public class DemoController { @GetMapping("/demo") @RateLimit(10) // 每秒限制10个请求 public String demo() { return "Hello World!"; } } ``` 以上代码实现了一个简单的接口限流功能,可以根据实际需求进行调整。需要注意的是,这种方式只适用于单机部署的场景,如果是分布式部署的系统,需要考虑使用分布式限流方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值