接口防刷限流
第一种 : 基础原理思路 :
1. 接口防刷主要是限制同一IP地址在一定时间内的访问次数
2. 同一IP每次访问,经过zuul网关的时候进行验证,
3. 利用IP作为redis的key,去查询此IP的访问次数 , 当第一次访问时,无key ,则设置key ,并设置过期时间
4. 接下来的每次访问都会通过以上方式去验证规定时间内,如一分钟内,是否访问超过20次,超过后则不放行
第二种: Spring Cloud Zuul通过zuul-ratelimit实现限流
spring cloud zuul-ratelimit,是专门针对 zuul 编写的限流库,提供来4种限流策略:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-maDadNyz-1600085219312)(C:\Users\白米白9999\AppData\Roaming\Typora\typora-user-images\1600083629825.png)]](https://img-blog.csdnimg.cn/20200914200727197.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NzA1NzgyMA==,size_16,color_FFFFFF,t_70#pic_center)
多种粒度临时变量储存方式
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UaYKd3IQ-1600085219314)(C:\Users\白米白9999\AppData\Roaming\Typora\typora-user-images\1600083827356.png)]](https://img-blog.csdnimg.cn/20200914200834249.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NzA1NzgyMA==,size_16,color_FFFFFF,t_70#pic_center)
yml配置参考-借鉴
ratelimit:
key-prefix: springcloud-book #按粒度拆分的临时变量key前缀
enabled: true #启用开关
repository: IN_MEMORY #key存储类型,默认是IN_MEMORY本地内存,此外还有多种形式
behind-proxy: true #表示代理之后
default-policy: #全局限流策略,可单独细化到服务粒度
limit: 2 #在一个单位时间窗口的请求数量
quota: 1 #在一个单位时间窗口的请求时间限制
refresh-interval: 3 #单位时间窗口
type:
- user #可指定用户粒度
- origin #可指定客户端地址粒度
- url #可指定url粒度
policies:
client-a:
limit: 5
quota: 5
efresh-interval: 10
yml配置参考–借鉴
#按粒度拆分的临时变量key前缀
zuul.ratelimit.key-prefix=springcloud-book
zuul.ratelimit.enabled=true
#key存储类型,默认是IN_MEMORY本地内存,此外还有多种形式
zuul.ratelimit.repository=IN_MEMORY
zuul.ratelimit.behind-proxy=true
#在一个单位时间窗口的请求数量
zuul.ratelimit.default-policy.limit=500
#在一个单位时间窗口的请求时间限制
zuul.ratelimit.default-policy.quota=2000
#单位时间窗口
zuul.ratelimit.default-policy.refresh-interval=60
#可指定限流粒度,user-用户粒度,origin-客户端地址粒度,url-url粒度
zuul.ratelimit.default-policy.type=url
通俗讲:就跟电梯限流一样,一次上下周期(zuul.ratelimit.default-policy.refresh-interval),限制只能上21人(zuul.ratelimit.default-policy.limit),不超过1600kg(zuul.ratelimit.default-policy.quota)
需要依赖
<dependency>
<groupId>com.marcosbarbero.cloud</groupId>
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
写一个拦截返回,友好提示
@Component
public class ErrorResponseJSONFilter extends ZuulFilter {
public static final String DEFAULT_ERR_MSG = "系统繁忙,请稍后再试";
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
return 10;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
try {
HttpServletRequest request = ctx.getRequest();
String rateLimitExceeded = (String) ctx.get("rateLimitExceeded");
String message = null;
if("true".equals(rateLimitExceeded)){
message = "您请求速度太快了,请稍后再试.";
}
if(StringUtils.isBlank(message)){
message = DEFAULT_ERR_MSG;
}
ctx.getResponse().setContentType("application/json;charset=UTF-8");
ctx.getResponse().getWriter().write("{\"code\":500,\"msg\":\""+message+"\"}");
} catch (Exception e) {
e.printStackTrace();
String error = "Error during filtering[ErrorFilter]";
try {
ctx.getResponse().getWriter().write("{\"code\":500,\"msg\":\""+error+"\"}");
} catch (IOException e1) {
e1.printStackTrace();
}
}
return null;
}
}