PS:源码已上传Github, 欢迎指教。https://github.com/shileishmily/spring-cloud-x.git
什么是灰度发布呢?
要想了解这个问题就要先明白什么是灰度。灰度从字面意思理解就是存在于黑与白之间的一个平滑过渡的区域,所以说对于互联网产品来说,上线和未上线就是黑与白之分,而实现未上线功能平稳过渡的一种方式就叫做灰度发布。
上一节讲了Apollo作为配置中心的基本使用,但其更为强大的地方在于可以和Zuul+Eureka无缝集成,实现灰度发布。
本篇主要演示应用新版本发布后,我们只希望指定的用户路由到我们的新版本服务器,其他用户仍然访问我们的老版本,如下图:
图中会使用Zuul,Apollo,Eeureka,这在之前我们已经讲过,大家可以看看之前的文章。本篇除了要对spring-cloud-gateway模块进行改造,还要新建两个模块x-demo-springcloud-gray-provider,x-demo-springcloud-gray-consumer对灰度进行测试使用。服务提供者和消费者在我们之前的pay-service,order-service,user-service基础上进行改造也可以,为了让代码看的更清晰,我们选择新建两个模块演示。
1、请求首先到达Zuul(GrayFilter),此时Zuul拦截器从请求头中取出token,解析出对应的userId。
2、Zuul网关从Apollo配置中心拉取灰度用户列表(GrayUserConfig),然后根据灰度用户策略判断该用户是否是灰度用户。若是,则给该请求添加请求头及线程变量添加信息version=xxx;若不是,则不做任何处理放行
3、在Zuul拦截器执行完毕后,Zuul在进行转发请求时会通过负载均衡器Ribbon。
4、负载均衡Ribbon被重写。当请求到达时候,Ribbon会取出Zuul存入线程变量值version。与此同时,Ribbon还会取出所有缓存的服务列表(定期从eureka刷新获取最新列表)及其该服务的metadata-map信息。然后取出服务metadata-map的version信息与线程变量version进行判断对比,若值一直则选择该服务作为返回。若所有服务列表的version信息与之不匹配,则返回null,此时Ribbon选取不到对应的服务则会报错!
5、当服务为非灰度服务,即没有version信息时,此时Ribbon会收集所有非灰度服务列表,然后利用Ribbon默认的规则从这些非灰度服务列表中返回一个服务。
6、Zuul通过Ribbon将请求转发到consumer服务后,可能还会通过fegin或resttemplate调用其他服务,如provider服务。但是无论是通过fegin还是resttemplate,他们最后在选取服务转发的时候都会通过Ribbon。
7、那么在通过fegin或resttemplate调用另外一个服务的时候需要设置一个拦截器,将请求头version=xxx给带上,然后存入线程变量。
8、在经过fegin或resttemplate 的拦截器后最后会到Ribbon,Ribbon会从线程变量里面取出version信息。然后重复步骤(4)和(5)
参考:https://segmentfault.com/a/1190000017412946