限流用法,时机:请求被转发之前调用。
- 令牌桶限流
- 一段时间里面往令牌桶里面放令牌,需求从令牌里拿令牌,拿不到(说明名额满了)就等着不给访问
package com.imooc.apigateway.filter;
import com.google.common.util.concurrent.RateLimiter;
import com.imooc.apigateway.exception.RateLimitException;
import com.netflix.zuul.ZuulFilter;
import org.springframework.stereotype.Component;
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;
/**
* 限流
*/
public class RateLimitFilter extends ZuulFilter{
// 谷歌提供的guava组件实现令牌桶的场景,每秒钟往里面放100个令牌。
private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);
/**
* to classify a filter by type. Standard types in Zuul are "pre" for pre-routing filtering,
* "route" for routing to an origin, "post" for post-routing filters, "error" for error handling.
* We also support a "static" type for static responses see StaticResponseFilter.
* Any filterType made be created or added and run by calling FilterProcessor.runFilters(type)
*
* @return A String representing that type
*/
public String filterType() {
return PRE_TYPE;
}
/**
* filterOrder() must also be defined for a filter. Filters may have the same filterOrder if precedence is not
* important for a filter. filterOrders do not need to be sequential.
*
* @return the int order of a filter
*/
public int filterOrder() {
return SERVLET_DETECTION_FILTER_ORDER - 1;
}
/**
* a "true" return from this method means that the run() method should be invoked
*
* @return true if the run() method should be invoked. false will not invoke the run() method
*/
public boolean shouldFilter() {
return true;
}
/**
* if shouldFilter() is true, this method will be invoked. this method is the core method of a ZuulFilter
*
* @return Some arbitrary artifact may be returned. Current implementation ignores it.
*/
public Object run() {
if (!RATE_LIMITER.tryAcquire()) {
throw new RateLimitException();
}
return null;
}
}