开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情
自定义限流过滤器和和访问日志过滤器
1.限流过滤器(对单位时间段的网络请求进行限制,采用的是令牌桶算法,如果超过系统预设的值,则进行拒绝访问,反之则放行)
@Slf4j
@Component
@SuppressWarnings("all")
public abstract class RateLimiterFilter extends AbstractPreZuulFilter {
//每秒可以得到两个令牌
RateLimiter rateLimit = RateLimiter.create(2.0);
@Override
protected Object cRun() {
HttpServletRequest request = context.getRequest();
if(rateLimit.tryAcquire()){
log.info("get rate token success");
return success();
}else{
log.info("rate limit:{}",request.getRequestURI());
return fail(402,"error: rate limit");
}
}
@Override
public int filterOrder() {
return 2;
}
}
-代码说明:
- @SuppressWarnings("all"):抑制所有类型的警告
- RateLimiter rateLimit = RateLimiter.create(2.0):每秒获取两个令牌,这值我们可以根据具体场景进行设置
- acquire的使用是为了将所有的请求平滑地分布到后续的时间段内,但有的时候,请求实在太多了,我们需要对调用过于频繁的请求给予拒绝服务的响应,此时就需要用到tryAcquire了,返回值true说明可以请求,false说明请求太频繁了
- filterOrder:根据具体场景进行设置
2访问日志过滤器
2.1日志请求之前PreRequestFilter
public abstract class PreRequestFilter extends AbstractPreZuulFilter {
@Override
protected Object cRun() {
context.set("startTime", System.currentTimeMillis());
return success();
}
@Override
public int filterOrder() {
return 0;
}
}
代码说明:
- context.set("startTime", System.currentTimeMillis()):设置请求开始的时间
2.2新建AccessLogFilter(计算时间差)
@Slf4j
@Component
public abstract class AccessLogFilter extends AbstractZuulFilter {
@Override
protected Object cRun() {
HttpServletRequest request = context.getRequest();
// 从 PreRequestFilter 中获取设置的请求时间戳
Long startTime = (Long) context.get("startTime");
String uri = request.getRequestURI();
long duration = System.currentTimeMillis() - startTime;
// 从网关通过的请求都会打印日志记录: uri + duration
log.info("uri: {}, duration: {}", uri, duration);
return success();
}
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
}
}
代码说明:
- Long startTime = (Long) context.get("startTime"):获取请求之前的时间
- String uri = request.getRequestURI():获取请求uri信息
- long duration = System.currentTimeMillis() - startTime:请求相应时间差
- FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1:post 过滤器可以有很多个,我们定义的只是其中一个,系统也会有其他的 post 类型过滤器;我这里指定的顺序含义就是在系统的最后一个 post 过滤器执行之前