应用管理与运维平台 ServiceStage应用管理与运维平台 ServiceStage

更新时间:2021/08/05 GMT+08:00
分享

基于动态配置的流量特征治理介绍

基于动态配置的流量特征治理旨在提供一种通用的,适合不同语言、不同微服务开发框架的治理规则。治理规则规定了微服务治理的过程、治理的策略,可以使用不同的开发框架、技术实现治理规则约定的治理能力。

您可以在Java Chassis、Go Chassis、Spring Cloud、Dubbo中使用该功能。

Java Chassis提供了实现SDK,可以将其用于其他开发框架。SDK默认采用Resilience4j实现治理过程。规范没有约束治理过程的实现框架,可以很方便的使用其他的治理框架实现治理过程。

治理过程

治理过程可以从如下两个不同的角度进行描述:

  • 从管理流程上,可以分为流量标记和设置治理规则两个步骤。系统架构师将请求流量根据特征打上标记,用于区分一个或者一组代表具体业务含义的流量,然后对这些流量设置治理规则。
  • 从处理过程上,可以分为下发配置和应用治理规则两个步骤。 可以通过配置文件、配置中心、环境变量等常见的配置管理手段下发配置。微服务SDK负责读取配置,解析治理规则,实现治理效果。

治理策略

治理策略分两部分进行描述,一部分描述流量标记, 一部分描述治理规则。

可以根据请求的特征进行流量标记,示例如下:

servicecomb:
  matchGroup:
    userLoginAction: |
      matches:
        - apiPath:
            exact: "/login"
          method:
            - POST
        - headers
          Authentication: 
            prefix: Basic

示例定义了一个流量特征userLoginAction,如果流量的apiPath=/login&method=POST, 或者请求头Authentication=Basic*,那么认为这个流量是一个登录操作。

定义好流量特征后,就可以设置治理规则,示例如下:

servicecomb:
  rateLimiting:
    userLoginAction: |
      rate: 100

示例设置流量特征userLoginAction的限流策略是100TPS。

规范参考

  • 流量标记
    示例如下:
    servicecomb:
      matchGroup:
        userLoginAction: |
          matches:
            - name: loginMethod
              apiPath:
                exact: "/login"
              method:
                - POST
            - name: authHeader
              headers
                Authentication: 
                  prefix: Basic
    

    一个流量对应一个Key,userLoginAction为Key的名称。 一个流量可以定义多个标记规则,每个标记规则里面可以定义apiPath,method,headers匹配规则。 不同标记规则是或的关系,匹配规则是与的关系。

    
    

    在match中提供了一系列的算子来对apiPath或者headers进行匹配:

    • exact : 精确匹配。
    • prefix: 前缀匹配。
    • suffix: 后缀匹配。
    • contains: 包含, 目标字符串是否包含模式字符串。
    • compare: 比较,支持>、<、>=、<=、=、!=符号匹配。处理时会把模式字符串和目标字符串转化为Double类型进行比较,支持的数据范围为Double的数据范围。在进行=和!=判断时,如果二者的差值小于1e-6就视为相等。例如模式串为>-10,会对大于-10以上的目标串匹配成功。

    流量标记可以在不同的应用层实现,比如:在提供REST接口的服务端,可以通过HttpServletRequest获取流量信息;在RestTemplate调用的客户端,可以从RestTemplate获取流量信息。

    不同的框架和应用层,提取信息的方式不一样。实现层通过将特征映射到GovernanceRequest来屏蔽差异。使得在不同的框架、不同的应用层都可以使用治理。

    public class GovernanceRequest {
      private Map<String, String> headers;
    
      private String uri;
    
      private String method;
    }
  • 限流
    示例如下:
    servicecomb:
      rateLimiting:
        userLoginAction: |
          limitRefreshPeriod: 1000 //新增许可间隔时间,单位默认毫秒,支持Duration类型时间 
          rate: 1 //许可数量  
    

    限流规则借鉴了Resilience4j的思想,作用在服务端,其原理为:

    每隔limitRefreshPeriod的时间会加入rate个新许可,就可以最多接受rate个请求,超过的将被限流,返回响应码429。

  • 重试

    根据重试时间间隔的是否固定,分为固定间隔重试和指数间隔重试两种策略,默认重试策略为固定间隔重试。

    固定间隔重试示例如下:

    servicecomb:
      retry:
        userLoginAction: |
          maxAttempts: 3 //最大重试次数
          retryOnResponseStatus: [502,503,5xx] //响应码,通过响应码列表指定重试场景,默认是502,5xx表示匹配500-599的响应码
          waitDuration:0 //重试,单位默认毫秒,支持Duration类型时间

    指数间隔重试策略示例如下:

    servicecomb:
      retry:
        userLoginAction: |
          maxAttempts: 3 //最大重试次数
          retryOnResponseStatus: [502,503,5xx] //响应码,通过响应码列表指定重试场景,默认是502,5xx表示匹配500-599的响应码
          retryStrateg: RandomBackoff //重试策略,默认为FixedInterval固定时间间隔策略
          initialInterval:1000 //基准时间间隔,最小值为10,单位默认毫秒,支持Duration类型时间
          multiplier: 2.0f //乘积因子,单位为float,取值范围大于1.0

    重试规则借鉴了Resilience4j的思想,作用在客户端,其原理为:

    如果响应的错误码(502,503)和返回值的计算结果满足重试条件,并且异常在重试异常清单里面,则进行重试,下一次重试等待时间为waitDuration。重试等待时间和具体的框架与运行机制有关:

    同步框架,重试等待时间必须大于等于0。

    异步框架,重试等待时间必须大于0,否则不会重试,并且重试是在独立的线程池里面执行的。

    重试条件是框架相关的,通过扩展RetryExtension, 不同框架实现机制可能不同:

    public interface RetryExtension {
      boolean isRetry(List<Integer> statusList, Object result);
      Class<? extends Throwable>[] retryExceptions();
    }
  • 熔断

    示例如下:

    servicecomb:
      circuitBreaker:
        userLoginAction: |
          failureRateThreshold:50 //失败率(请求)百分比阈值,取值范围(0,100.0]
          slowCallRateThreshold: 100 //慢调用率阀值,取值范围取值范围(0,100.0]
          slowCallDurationThreshold: 60000 //慢调用请求阈值定义,响应时间超过该阈值的请求都是慢调用,单位默认毫秒,支持Duration类型时间
          minimumNumberOfCalls: 100 //达到熔断条件的请求数量下限
          slidingWindowType: count //滑动窗口计数类型,默认为time类型
          slidingWindowSize: 100 //滑动窗口大小,当为滑动窗口类型为time类型时,窗口大小表示时间,单位为秒

    熔断规则借鉴了Resilience4j的思想,作用在服务端,其原理为:

    达到指定failureRateThreshold错误率或者slowCallRateThreshold慢请求率时进行熔断,返回响应码429,慢请求通过SlowCallDurationThreshold定义。minimumNumberOfCalls是达到熔断要求的最低请求数量门槛,例如,若minimumNumberOfCalls是10,为计算失败率,则最小要记录10个调用。若只记录了9个调用,即使9个都失败,CircuitBreaker也不会打开。slidingWindowType指定滑动窗口类型,默认可选count/time, 分别是基于请求数量窗口和基于时间窗口。若滑动窗口为count,则最近slidingWindowSize次的调用会被记录和统计。若滑动窗口为time,则最近slidingWindowSize秒中的调用会被记录和统计。slidingWindowSize指定窗口大小,根据滑动窗口类型,单位可能是请求数量或者秒。

  • 隔离仓

    示例如下:

    servicecomb:
      bulkhead:
        userLoginAction: |
          maxConcurrentCalls: 1000 //最大信号量
          maxWaitDuration: 0 //最大等待时间间隔,单位默认毫秒,支持Duration类型时间

    隔离仓规则借鉴了Resilience4j的思想,作用在服务端,其原理为:

    隔离仓使用了信号量机制,当大量并发请求进入时,如果信号量存在剩余,进入系统的请求会直接获取信号量并开始业务处理。当信号量全被占用时,请求将会进入阻塞状态,如果maxWaitDuration时间内无法获取到信号量则系统会拒绝这些请求。若请求在阻塞计时maxWaitDuration内获取到了信号量,那么将直接获取信号量并执行相应的业务处理。开启隔离仓时,返回错误码429。在异步框架,建议maxWaitDuration设置为0,防止阻塞事件派发线程。

分享:

    相关文档

    相关产品