美文网首页
spring cloud网关通过Zuul RateLimit 限

spring cloud网关通过Zuul RateLimit 限

作者: 泥与森 | 来源:发表于2019-04-01 14:38 被阅读0次

    目录

    在平常项目中为了防止一些没有token访问的API被大量无限的调用,需要对一些服务进行API限流。就好比拿一些注册或者发验证码的一些接口,如果被恶意无限的调用,多少会造成一些费用的产生,发短信或者邮件都是一些第三方接口,次数越多,当然费用也就越多了,严重的直接导致服务崩溃。spring cloud api-gateway中引入限流的配置还是必须的。

    引入依赖

    在pom文件中引入Zuul RateLimit的依赖

    
    <dependency>
        <groupId>com.marcosbarbero.cloud</groupId>
        <artifactId>spring-cloud-zuul-ratelimit</artifactId>
        <version>1.3.2.RELEASE</version>
    </dependency>
    

    配置信息

    
    更详细的配置解读下面有写,这里只是简单配置一下,以下这个配置就可以对服务进行限流了
    zuul:
      routes: 你的路由配置
        test:
          path: 
          serviceId: 
      ratelimit:
        enabled: true
        policies:
          test: 路由名
            limit: 限制次数
            refresh-interval: 刷新时间
            type: 类型
    
    

    RateLimit源码简单分析

    本地让自己的一个服务配置为一分钟内该服务的API只能访问十次,超过十次,网关就会报错

    zuul:
      routes:
        test:
          path: /api/test/**
          serviceId: hscf-cloud-test-9457
      ratelimit:
        enabled: true
        policies:
          test:
            limit: 10
            refresh-interval: 60
            type: origin  限流方式
    

    下面通过源码简要分析一下

    RateLimit类是继承ZuulFilter,内中的变量不难看出就是我们在yml文件中配置的属性值。RateLimit内中的部分源码,filterType为“pre”表示在每一个API访问之前进行拦截,LIMIT_HEADER,REMAINING_HEADER,RESET_HEADER这三个变量应该就是获取我们配置的访问次数,还有记录该时间内剩余的访问次数。

    public class RateLimitFilter extends ZuulFilter {
        public static final String LIMIT_HEADER = "X-RateLimit-Limit";
        public static final String REMAINING_HEADER = "X-RateLimit-Remaining";
        public static final String RESET_HEADER = "X-RateLimit-Reset";
    
        public String filterType() {
            return "pre";
        }
        public int filterOrder() {
            return -1;
        }
        public boolean shouldFilter() {
            return this.properties.isEnabled() && this.policy(this.route()).isPresent();
        }
    

    主体逻辑run()中进行判断。先通过this.policy(route).ifPresent((policy)判断policy配置信息是否存在,存在的话会读
    取到当前的限制值,还剩余的限制值,最终判断剩余的限制值是否小于0,小于0的话就会报出太多请求的异常
    TOO_MANY_REQUESTS(429, "Too Many Requests")

        public Object run() {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletResponse response = ctx.getResponse();
            HttpServletRequest request = ctx.getRequest();
            Route route = this.route();
            this.policy(route).ifPresent((policy) -> {
                String key = this.rateLimitKeyGenerator.key(request, route, policy);
                Rate rate = this.rateLimiter.consume(policy, key);
                response.setHeader("X-RateLimit-Limit", policy.getLimit().toString());
                response.setHeader("X-RateLimit-Remaining", String.valueOf(Math.max(rate.getRemaining().longValue(), 0L)));
                response.setHeader("X-RateLimit-Reset", rate.getReset().toString());
                if(rate.getRemaining().longValue() < 0L) {
                    ctx.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
                    ctx.put("rateLimitExceeded", "true");
                    throw new ZuulRuntimeException(new ZuulException(HttpStatus.TOO_MANY_REQUESTS.toString(), HttpStatus.TOO_MANY_REQUESTS.value(), (String)null));
                }
            });
            return null;
        }
    。。。。。。
    

    控制台的异常信息,异常code为429,也就是太多请求的异常:TOO_MANY_REQUESTS(429, "Too Many Requests")

    RateLimit详细的配置信息解读

    zuul:
    
        ratelimit:
    
            key-prefix: your-prefix  #对应用来标识请求的key的前缀
    
            enabled: true
    
            repository: REDIS  #对应存储类型(用来存储统计信息)
    
            behind-proxy: true  #代理之后
    
            default-policy: #可选 - 针对所有的路由配置的策略,除非特别配置了policies
    
                 limit: 10 #可选 - 每个刷新时间窗口对应的请求数量限制
    
                 quota: 1000 #可选-  每个刷新时间窗口对应的请求时间限制(秒)
    
                  refresh-interval: 60 # 刷新时间窗口的时间,默认值 (秒)
    
                   type: #可选 限流方式
    
                        - user
    
                        - origin
    
                        - url
    
              policies:
    
                    myServiceId: #特定的路由
    
                          limit: 10 #可选- 每个刷新时间窗口对应的请求数量限制
    
                          quota: 1000 #可选-  每个刷新时间窗口对应的请求时间限制(秒)
    
                          refresh-interval: 60 # 刷新时间窗口的时间,默认值 (秒)
    
                          type: #可选 限流方式
    
                              - user
    
                              - origin
    
                              - url
    
    
    • url类型的限流就是通过请求路径区分
    • origin是通过客户端IP地址区分
    • user是通过登录用户名进行区分,也包括匿名用户

    目前只是将网关中的限流方式使用连起来,源码中的原理知道了一下,后续可以继续进行扩展,可以针对请求上的参数进行请求拦截限流

    相关文章

      网友评论

          本文标题:spring cloud网关通过Zuul RateLimit 限

          本文链接:https://www.haomeiwen.com/subject/hudvbqtx.html