zuul接口限流之spring-cloud-zuul-ratelimit

网上找到的资料大多是针对服务限流,接口限流的资料很少,而且配置复杂,于是我结合网上资料和自己的实践,去粗取精,形成了适合自己的极简配置。

导入依赖


  com.marcosbarbero.cloud
  spring-cloud-zuul-ratelimit
  2.4.0.RELEASE

配置参考 

zuul:
  routes:
    user-web:
      path: /user/**
      serviceId: jd-user-web
      stripPrefix: false
    order-web:
      path: /order/**
      serviceId: jd-order-web
      stripPrefix: false
  ratelimit:
    key-prefix: ${spring.application.name}-rate-limit #缓存key的前缀
    enabled: true #开启限流
    repository: REDIS #key存储方式为redis
    behind-proxy: true # 当前网关是代理后的请求,需要获取Header中的X-FORWARDED-FOR以便获取源IP
    policy-list: #指定服务策略,优先默认
      user-web: #路由ID
        - limit: 5 #每个刷新窗口请求数
          quota: 3 #每个刷新窗口总请求时间(秒)
          refresh-interval: 15 #刷新窗口时间(秒),默认60秒
          type:
            - url=/user/getUser
        - limit: 5 #每个刷新窗口请求数
          quota: 3 #每个刷新窗口总请求时间(秒)
          refresh-interval: 15 #刷新窗口时间(秒),默认60秒
          type:
            - url=/user/getWxUser
      order-web:
        - limit: 5 #每个刷新窗口请求数
          quota: 3 #每个刷新窗口总请求时间(秒)
          refresh-interval: 15 #刷新窗口时间(秒),默认60秒
          type:
            - url=/order/shop/list

关键参数解读

以下面参数为例,进行详细说明。

user-web: #路由ID

    limit: 5 #每个刷新窗口请求数
    quota: 3 #每个刷新窗口总请求时间(秒)
    refresh-interval: 15 #刷新窗口时间(秒),默认60秒

user-web:此处不是serviceId,网上都是误导的,我管他叫路由ID,如果serviceId和路由ID不一致,此次要取路由ID,否则,会导致限流不起作用。

limit: 请求总次数。15秒内只能请求5次,超过了报 "429 TOO_MANY_REQUESTS"。
quota: 请求累计时长。每次请求的时间,累计不能超过3秒,假如前4次请求总耗时已经超过3秒,那么第5次请求报"429 TOO_MANY_REQUESTS"。这个参数一般可以省略。
refresh-interval: 统计请求的时间窗口长度。从第一次请求开始,在缓存里设置一个15秒后失效的key,key由key-prefix + routeId + url拼接成。
如果在第5秒的时候,请求超过了5次,那么后续请求都报"429 TOO_MANY_REQUESTS",只能继续等待10秒缓存失效后,再次请求恢复正常。这就是“突刺现象”,也是这个限流框架的缺点。

第一次接口调用后,可以看到缓存中生成的key:

jd-zuul-dev-rate-limit:user-web:/user/getUser:/user/getUser
jd-zuul-dev-rate-limit:user-web:/user/getUser:/user/getUser-quota

自定义异常信息

zuul接口限流之spring-cloud-zuul-ratelimit_第1张图片

这是网上的方式。实际上RateLimiterErrorHandler无法捕获到限流异常信息429 TOO_MANY_REQUESTS,也就不能自定义异常返回信息。得通过ExceptionHandler返回自定义异常信息。

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExceptionHandler implements ErrorController {

    @Override
    public String getErrorPath() {

        return "error";
    }

    @RequestMapping(value="/error")
    public Rsp error(){
        return new Rsp(RSP_CODE_ERROR, "系统忙,请稍后再试");
    }

}

网关限流参数

zuul接口限流之spring-cloud-zuul-ratelimit_第2张图片

自定义Key策略 

如果希望自己控制key的策略,可以通过自定义RateLimitKeyGenerator的实现来增加自己的策略逻辑。

例如:根据请求上的参数来对请求进行限流。比如有一个请求是http://localhost:8765/api-a//hello2?name=kevin,对相同的name值进行限流。我们设置了1分钟内,限流10次,那么如果1分钟内,name是kevin的请求超过10次,就会发生限流。

RateLimitKeyGenerator的实现:

zuul接口限流之spring-cloud-zuul-ratelimit_第3张图片

附记

这篇文章写的很好,各种限流框架做了一个对比,列出各种优缺点,原理分析等等。

https://segmentfault.com/a/1190000020745218

zuul接口限流之spring-cloud-zuul-ratelimit_第4张图片

 

你可能感兴趣的:(springboot,java)