zoukankan      html  css  js  c++  java
  • SpringCloud zuul 网关限流分析

    最近项目中 spring cloud zuul 运用到限流功能,打算配置一下就直接使用,不过在压测与调优过程中遇到一些没有预测到的问题,附上排查与解析结果

    yml、pom配置

    强烈推荐,按最新github上的文档配,可以避免搜到一些已经废弃不用的配置方式!

    https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit

    我的一些配置,可以直接套用:

    zuul:
      routes:
      #路由、重试等zuul其他配置省略
      #限流
      ratelimit:
        enabled: true # 开启限流功能
        behind-proxy: true # 开启则限流与业务访问是异步的,相当于rateLimitFilter先放过;默认是false
        repository: REDIS # 可选REDIS、CONSUL、JPA等,老版本还有本地内存可选
        policy-list:
          myProject1:
            - limit: 5 # 这种配置方式相当于:10分钟内允许5个请求访问/api/test/info接口
              refresh-interval: 10
              type:
                - url_pattern=/api/test/info
          myProject2:
            - limit: 3000
              refresh-interval: 1 # 更常见的配置是这种,一秒允许3k个,相当于配qps限制
              type:
                - url_pattern=/api/test2/info
    - limit: 300 refresh-interval: 1 # 如果同一个服务有多个需要限流的url,可以这样 type: - url_pattern=/api/test2/info2

    pom需要:

    <dependency>
        <groupId>com.marcosbarbero.cloud</groupId>
        <artifactId>spring-cloud-zuul-ratelimit</artifactId>
        <version>${latest-version}</version>
    </dependency>

    如果 repository 选择用 REDIS,还需要:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    启动,检查限流功能生效,并且不影响不限流的其他接口!至此解决了限流有无的问题!

    返回处理

    我们可能需要对触发限流的情况做监控、报警等,需要识别由限流导致的异常返回

    1. 推荐使用默认的 RateLimiterErrorHandler,直接写自己需要的处理就行
    2. zuul触发限流后会抛出 http 429,可以针对这个错误码对response包装
    3. 也可以在全局异常处理中,判断出现的异常是否是 RateLimitExceededException

    其他配置方式 

    目前项目中只用到了对特定url的qps限流,zuul ratelimit 还提供对user、http method、url正则等

    性能分析

    限流配置之前,单实例压测,qps大概能到2500;配个2300的限流,开开心心启动服务,启动压测!

     

    WTF!限流对性能的影响已经超过了限流配置本身。。一定是我哪里不对TAT 

    开始排查问题,查实现原理

    zuul 限流的入口是zuul的 RateLimitPreFilter

    其中 rateLimitKeyGenerator.key 所生成的redis key较长,规则为 前缀(默认为springBoot项目名) + : + zuul项目名 + : + matcher(和限流策略有关,这里是URL_PATTERN) + : + matcher(再来一遍)

    如果项目名和url较长,可能出现key例如:my-test-project-gateway:my-sub-project:/api/test2/info2:/api/test2/info2

    不过监控看redis暂不是短板,继续查

    限流的实现,通过 rateLimiter.consume 方法

    继续往下看,calcRemainingLimit 方法,内部调用了calcRemaining 方法:

    原理不难,利用redis incr命令,每次计算当前过期窗口内还剩几次,来决定是否限流,安全又高效

    但是,上一张图 rateLimiter.consume 方法增加了 synchornized,怀疑是这个原因

    其中 redisTemplate.opsForValue().increment(key, usage) 已经没有并发问题了,这里感觉不用再 synchornized +_+*

    发现也有同僚遇到了这个问题,建议是重写这个类,去掉synchornized

    https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit/issues/96

    讨论中有人主张去掉synchornized,有人主张保留

    决定还是要去掉synchornized,压测

    完美!!!

    再验证一下对无限流的接口是否无影响,确保可用

    其他网关限流方式

    目前刚开始接触,也还在探索中,可以一起讨论下

    1. spring cloud gateway:

    • 也是成熟的技术,并且大部分文章分析 Finchley版本的 gateway比 zuul 1.x系列的性能和功能整体要好
    • 目前 spring cloud 没集成 Zuul 2.x,虽然zuul 2.x使用了异步无阻塞式的 API,性能改善明显
    • 实现思想很简洁,令牌桶,只有50行lua,其中有4次redis调用
    • 可以通过monitor命令看出:
    request_rate_limiter.lua
    测试配置为:
    redis-rate-limiter.replenishRate: 500 允许每秒500个请求
    redis-rate-limiter.burstCapacity: 5000 令牌桶容量5000
    1. 查询当前桶里剩余令牌数
    1590493327.354684
    [0 lua] "get" "request_rate_limiter.{/app/test/info}.tokens"
    2. 查询上次取牌的时间
    注意:通过当前时间,和上次取牌的时间差,即可在lua中计算出这段时间内新补充进桶里的令牌数,不用每秒真正补充进桶 1590493327.354696 [0 lua] "get" "request_rate_limiter.{/app/test/info}.timestamp"
    3. 把这次取的1个令牌,和这段时间内需要重新补充进桶的令牌整合,更新最新令牌数
    注意:超时时间为 (brustCapacity/replenishRate)*2,感觉不乘2也行,只要保证超时时间 >= 桶重新装满的时间就够了,乘2是否完全是为了保险? 1590493327.354712 [0 lua] "setex" "request_rate_limiter.{/app/test/info}.tokens" "20" "4999"
    4. 更新最新取牌时间 1590493327.354727 [0 lua] "setex" "request_rate_limiter.{/app/test/info}.timestamp" "20" "1590493327"

    2. 自己用filter+redis、guava rate limiter等实现

    可以做单机缓存、自己定制规则

    总结

    目前的测试是单机压测,集群下压测或许还会在别的地方遇到瓶颈

    单实例配置、zuul进程数和其他配置、redis集群性能、业务代码,都有提升的空间

    还需要继续排查与优化

    micheal.li > 阿智
    micheal.li > mikeve@163.com
  • 相关阅读:
    Poj2033
    CodeForces 540
    CodeForces 548
    LeetCode#2 Add Two Numbers
    CodeForces 544A
    POJ 2431Expedition
    HLG1116-选美大赛
    清华学堂 列车调度(Train)
    清华学堂 LightHouse
    清华学堂 Range
  • 原文地址:https://www.cnblogs.com/loveCheery/p/12965792.html
Copyright © 2011-2022 走看看