乐趣区

关于spring-cloud:spring-cloud-gatewayribbon-组合指定版本权重分流简易灰度发布实现

0. 参考

文章 1 ribbon 中应用 HystrixRequestVariableDefault 的一个注意事项

文章 2 SpringCloud 灰度公布实际(附源码)zuul 实现的能够参考。

1. 思路

革新 gataway 的 ### Weight Route Predicate Factory,在指定权重的同时指定每个对应权重的服务的版本号。次要须要改写的中央是要在分流之后,将版本号传给 ribbon,ribbon 在做负载平衡抉择的时候,依据传入的版本号,与服务的 eureka.matedata 中的 version 匹配,从而达到灰度公布的目标。
gateway 的配置相似如下,VersionWeight 为重写的断言工厂。

    - id: temp_old
      uri: lb://TEMPLATE
      predicates:
        - Path=/temp/**
        - VersionWeight=group1, 10, v1
      filters:
        - StripPrefix=1
    - id: temp_new
      uri: lb://TEMPLATE
      predicates:
        - Path=/temp/**
        - VersionWeight=group1, 1, v2
      filters:
        - StripPrefix=1

2. 考察革新点

debug 后晓得了整个申请程序

客户端 -> gateway filter -> LoadBalancerClientFilter -> (如果应用 ribbon) RibbonLoadBalancerClient-> (某个 Rule) XXXAvoidanceRule -> (对应的 Predicate) XXXAvoidancePredicate

所以抉择的服务的要害就是 Ribbon 的 rule 和 Predicate

步骤

  1. 写一个 grayContext, 基于 threadlocal 解决 version 的上下文传递。
  2. 自定义负载策略:负载策略的要害是 Rule 和 Predicate,Rule 继承 PredicateBasedRule, Predicate 继承 AbstractServerPredicate,实现 Predicate 中的 apply 办法 此办法是负载策略外围(逻辑:从 grayContext 获取 version,与服务的 eureka.matedata 中的 version 匹配。匹配上则为指标服务)
  3. 改写权重断言策略:改写 WeightRoutePredicateFactory,在 Factory 分流实现后,把路由中配置的 version 放入到 grayContext 中。并且要将 vesion 放入到 request 的 head 中,用来向下传递。

    下面是对 gateway 的革新,通过革新后,gateway 散发的时候就依据 version 能指定申请的服务器,接下来是微服务间通过 fegin 或者 restTemplate 调用时的革新,目标是将 version 持续往下传递

  4. 对 request 申请拦挡:在微服务中对 request 申请进行拦挡,将 request 中的 version 放到 grayContext 中
  5. 对 fegin 增加拦截器:实现 RequestInterceptor,从 grayContext 中取出 version 放在头部中。fegin 的 loadbanced 也是基于 ribbon 的,所以应用自定义负载策略进行散发,策略和 gateway 统一。
  6. 如果应用 restTemplate,增加拦截器:实现 ClientHttpRequestInterceptor,从 grayContext 中取出 version 放在头部中。

这样就将 version 串联起来,从而实现了指定流量到对应的服务。

留神点

如果断路器应用 Hystrix,要留神 Hystrix 用信号量隔离,没问题,如果应用线程池隔离,咱们基于 threadlocal 解决 version 就有效了,
hystrix 有提供对应的办法 应用 HystrixRequestVariableDefault
参考 文章 1 这篇文章中提到的应用形式,能了解 HystrixRequestVariableDefault 是个怎么的用法,其作用和 threadlocal 相似。

3. 待解决问题

  • 不应用 ribbon 的状况,引入 spring-cloud-loadbalancer,loadbalancer 和 ribbon 差蛮多,不反对主动刷新 serverlist,只有一个 RoundRobinLoadBalancer。会应用 ReactiveLoadBalancerClientFilter,要通过实现 ReactorServiceInstanceLoadBalancer 接口 来实现负载策略
    感觉没太大差,然而要本人实现主动刷新 serverlist。能够参考 ribbon 的做法来做。举荐是应用 spring-cloud-loadbalancer,因为 ribbon 是阻塞的。
  • 官网举荐应用 CircuitBreaker,因为 Hystrix 不保护了。CircuitBreaker 只有信号量隔离,能够间接应用 threadlocal。
退出移动版