经典的模型:令牌桶的模型
1、比如说在电商中的抢购:一点就说抢购已结束。其实没有结束,只是你没有获得这个令牌就已经没了,所以说它可以限流,电商里的限流也可以用队列。1.1、限流就是如何去限制它的流量,让这个流量尽量控制在可控制的范围当中。2、在微服务当中,做限流都有成熟的框架,谷歌为我们提供成熟的插件guava=>RateLimiter:这个类里面可以直接做限流。2.1、既然做限流是做所有的过滤器之前来处理的。
代码如下:只要这么做就可以达到很好的限流的作用。create方法中的参数permitsPerSecond, long warmupPeriod, TimeUnit unit
permitsPerSecond :当请求到来的速度超过了permitsPerSecond,保证每秒只处理permitsPerSecond个请求。
参数warmupPeriod和unit决定了其从冷却状态到达最大速率的时间
package com.example.userapigateway.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVLET_DETECTION_FILTER_ORDER;
@Component
public class RateLimiters extends ZuulFilter {
//创建一个容量为100的令牌桶
//每次请求的时候都会获取这个令牌桶
public static final com.google.common.util.concurrent.RateLimiter RATE_LIMITER =
com.google.common.util.concurrent.RateLimiter.create(1,2, TimeUnit.SECONDS);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return SERVLET_DETECTION_FILTER_ORDER-1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
//获取令牌桶里的令牌
//如果为true,就是获取到了令牌,然后就直接放行
//如果没有获取到的话,直接就抛异常了。
//如果是10003的话代表请求的速度太快了,我这边接收不了,
//接收不了的话就拿不到令牌了,相当于拿的时候这个令牌已经没了。
//所以需要等待放进来的时候才可以拿到。拿不到的原因是流量太大了,一下就拿不到了。
//限制了流量的速率。一个人可以拿多个令牌,看它的线程。
boolean flag = RATE_LIMITER.tryAcquire();
if(!flag){
context.setSendZuulResponse(false);
context.setResponseStatusCode(400);
}
return null;
}
}
3、去重启下gateway,然后用postman对接口的压测,一秒钟10次的请求,演示多线程的操作:
总结:zuul的限流就是这个流量不能让你一下子过来得太多,比如不能让10000个流量,或者让1百万个流量去流入到我们的服务里去了,这肯定是不允许的。以固定速率放入令牌,如果发现令牌满的话,直接就丢弃了,相当于就达到了限流的效果了。