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
步骤
- 写一个 grayContext, 基于 threadlocal 解决 version 的上下文传递。
- 自定义负载策略:负载策略的要害是 Rule 和 Predicate,Rule 继承 PredicateBasedRule, Predicate 继承 AbstractServerPredicate,实现 Predicate 中的 apply 办法 此办法是负载策略外围(逻辑:从 grayContext 获取 version,与服务的 eureka.matedata 中的 version 匹配。匹配上则为指标服务)
- 改写权重断言策略:改写 WeightRoutePredicateFactory,在 Factory 分流实现后,把路由中配置的 version 放入到 grayContext 中。并且要将 vesion 放入到 request 的 head 中,用来向下传递。
下面是对 gateway 的革新,通过革新后,gateway 散发的时候就依据 version 能指定申请的服务器,接下来是微服务间通过 fegin 或者 restTemplate 调用时的革新,目标是将 version 持续往下传递
- 对 request 申请拦挡:在微服务中对 request 申请进行拦挡,将 request 中的 version 放到 grayContext 中
- 对 fegin 增加拦截器:实现 RequestInterceptor,从 grayContext 中取出 version 放在头部中。fegin 的 loadbanced 也是基于 ribbon 的,所以应用自定义负载策略进行散发,策略和 gateway 统一。
- 如果应用 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。