网关限流比较简单的方式就是在pre的filter中使用令牌桶,因为是限流,所以过滤器排序要靠前,使用方法谷歌guava的RateLimiter组件,代码实现:
import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
/**
* 限流过滤器
*/
@Component
public class LimitFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return -100;
}
@Override
public boolean shouldFilter() {
return true;
}
//初始化一个令牌
private static final RateLimiter limit = RateLimiter.create(1);
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
if(limit.tryAcquire()){
System.out.println("请求通过");
return null;
}else{
System.out.println("被限流了");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
}
return null;
}
}
依赖的话不需要额外引入,如果引入了zuul之后就会自动加载依赖com.google.guava:guava:29.0-jre。
需要注意的事,对于网关来讲,zuul网关的实现都是Filter来实现,所以尽量不要在zuul网关中写RestController业务,因为对于ZuulFilter不会过滤自身的request请求。