优惠券项目-自定义过滤器

79 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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 过滤器执行之前