You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
首先我们来了解什么是灰度发布,灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行 A/B 测试,即让一部分用户继续使用产品特性 A,另外一部分用户开始使用产品特性 B,如果用户对特性 B 没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到特性 B 上。灰度发布可以保证整体系统的稳定性,在初始灰度时就可以发现、调整问题。
在很多的开源框架中也有灰度发布的功能,比如配置中心 Apollo 中,对于配置的修改,也可以选择灰度发布,推送到某个指定的节点,如果这个节点使用一段时间没有发生问题,那么就可以推送给全部节点。如果这个节点使用过程中出问题,那么直接回滚这个节点的配置即可,对于其他节点没有任何影响。如果没有灰度发布的功能,一旦改动所有节点都生效,一个节点出问题,所有的节点也都会受影响。
我们基于 Discovery 来自定义灰度路由策略以满足上面的灰度发布需求。首先定义一个配置实体类,对应的是 Apollo 中的配置信息,我们支持版本和 IP 端口的方式来进行灰度。
然后通过实现 DiscoveryEnabledStrategy 来决定对应的 Server 是否能够被转发,逻辑很简单,首先判断是否带 n-d-version 这类的请求头,如果有就不往下执行了,以外部带入的为准。最后获取 server 的版本跟配置里的版本进行比较,如果当前 server 的版本在配置里面存在,则说明这个版本是灰度的版本,不能被转发,直接过滤掉。
IP 端口判断的方式也是一样的,这是在网关中的处理方式,在内部服务中也是一样的处理方式,我这边为了方便就将代码复制了一份过去,大家可以进行简化,抽出来共用。如果我们的 article-service 需要发布新的版本,在发布之前会将元数据中的版本进行升级,然后在配置中心指定这个版本为灰度的版本,这样重新发布后正常请求就不会请求到这个灰度的服务。
The text was updated successfully, but these errors were encountered:
灰度发布
首先我们来了解什么是灰度发布,灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行 A/B 测试,即让一部分用户继续使用产品特性 A,另外一部分用户开始使用产品特性 B,如果用户对特性 B 没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到特性 B 上。灰度发布可以保证整体系统的稳定性,在初始灰度时就可以发现、调整问题。
在很多的开源框架中也有灰度发布的功能,比如配置中心 Apollo 中,对于配置的修改,也可以选择灰度发布,推送到某个指定的节点,如果这个节点使用一段时间没有发生问题,那么就可以推送给全部节点。如果这个节点使用过程中出问题,那么直接回滚这个节点的配置即可,对于其他节点没有任何影响。如果没有灰度发布的功能,一旦改动所有节点都生效,一个节点出问题,所有的节点也都会受影响。
了解完灰度发布的概念后,那么我们为什么需要灰度发布呢?因为灰度发布可以帮助我们解决以下三大问题。
灰度发布解决的第一个问题:服务数量多,业务变动频繁,发布频繁。
微服务架构下,拆分出来的服务数量成百上千,互联网的业务又是变动频繁的,一周一迭代很正常,基本上每周都要发布新功能,每次发布涉及的服务数量都比较多。发布过程中难免会出现问题,这个时候就需要考虑如何不影响现有的用户,灰度发布就能解决这个问题。
灰度发布解决的第二个问题:灰度发布能降低发布失败风险,减少影响范围。
通过灰度发布,先让一部分用户体验新的服务,或者只让测试人员进行测试,等功能正常后再全部发布,这样能降低发布失败带来的影响范围。
灰度发布解决的第三个问题:当发布出现故障时,可以快速回滚,不影响用户。
灰度发布只是先发布一部分功能,比如只发布一个节点,而这个节点不会接收正常用户的请求,只会根据灰度的规则来处理指定用户的请求,灰度后如果发现这个节点有问题,那么只需回滚这个节点即可,当然不回滚也没关系,通过灰度策略隔离,也不会影响正常用户。
灰度发布策略
灰度发布怎么去隔离请求呢,我们会定制一系列的策略来支持,最常见的策略有用户策略,客户端策略,服务策略。
用户策略
用户策略指的是对指定的用户进行灰度的转发,比如我想让用户 ID 为 100 的用户访问灰度的服务,这样就可以让指定的用户来体验灰度和测试。
客户端策略
客户端策略指的是对于指定的客户端可以让其体验灰度功能,最常见的就是 App 的内测功能了,平时你在用某个 App 时,有时会有消息推送,说你作为我们的优质用户,可以体验最新版的 App 功能,这个时候就相当于是一个内测版本,先让小部分用户去使用,然后观察这部分用户的使用情况,如果没有问题再发布真正的版本。
服务策略
服务策略指的是对于指定的服务,可以在发布后将其变成灰度服务,这时不会让正常用户请求到,一般是使用 IP 加上端口的方式来进行的。
当然还有其他的使用场景,比如线上某个服务出故障,需要花时间排查问题,又不能重启服务,重启意味着现场就被破坏了,这个时候可以将服务通过灰度的方式进行隔离,这样就不会影响正常的请求,然后再对这个服务进行故障的排查。
Discovery 原理
Discovery 是基于 Spring Cloud Discovery 服务注册发现、Ribbon 负载均衡、Feign 和 RestTemplate 调用等组件全方位增强的企业级微服务开源解决方案,包括灰度发布、灰度路由、服务隔离等功能。其 GitHub 地址为 https://github.com/Nepxion/Discovery。
在项目中使用 Discovery 来实现灰度发布非常简单,Discovery 支持多种策略,同时也支持主流的注册中心和配置。
Discovery 是一款功能强大的框架,我们可以用它来实现灰度发布、服务隔离等高级功能。它的实现原理也非常简单,灰度发布最重要的是需要能够识别请求,然后将请求转发到匹配的服务上,说到这里你应该能想到需要怎么去实现了,前面课时中我也有提到过,可以通过 Ribbon 的算法类来实现这些功能。
除了控制 Ribbon 的路由,还需要将客户端带来的灰度信息一层层传递下去,可以将信息从 HTTP 请求头中带过去。
从图中我们可以看出 Discovery 对注册中心的支持做得非常好,支持了目前主流的注册中心。有Nacos、Eureka、Redis、Zookeeper。
对配置中心的支持也同样非常好,支持了 Nacos、Apollo、Redis。可以将灰度发布的规则放入配置中心,修改实时生效。
Discovery 灰度发布实现
首先我们准备三个服务来作为灰度发布的演示,一个 Zuul 网关,一个 article 服务,一个 user 服务。调用流程是网关到 article 服务,article 服务中会调用 user 服务。默认运行中的服务是 V1 版本,当我们增加了新功能,需要发布 V2 版本时,需要对正式的用户不可见,只能让测试访问,等测试没问题后再对正式用户开放,然后停掉 V1 的版本。
然后,使用 Discovery 需要加入相关的 Maven 依赖,在网关中加入 Zuul、Eureka、Apollo 三个依赖,如果你不需要用配置中心也可以不用 Apollo 的依赖,如果你是其他的注册中心,也可以选择其他的依赖,Discovery 在这块支持得很好。
在 user 和 article 服务中,也需要加入对应的依赖,如果用了 Hystrix 的线程隔离,还需要加入 Discovery 的 Hystrix 模块依赖,主要是处理线程切换后 ThreadLocal 信息丢失的问题,这个我们在前面的课时中讲解过。
在实际工作中,线上机器资源是有限的,增加大量的机器会增加公司的成本。所以我们一般在部署新版本时不是重新部署一套,然后将流量切过去,而是将老的服务实例停掉,再替换成新版本的实例。
假设每个服务 2+ 节点以上,可以通过网关来做灰度发布,因为网关重启的几率小,即使重启仍有 Nginx 可以进行自动剔除。灰度发布的实现主要通过网关路由的内部服务,具体的步骤如下:
我们基于 Discovery 来自定义灰度路由策略以满足上面的灰度发布需求。首先定义一个配置实体类,对应的是 Apollo 中的配置信息,我们支持版本和 IP 端口的方式来进行灰度。
然后通过实现 DiscoveryEnabledStrategy 来决定对应的 Server 是否能够被转发,逻辑很简单,首先判断是否带 n-d-version 这类的请求头,如果有就不往下执行了,以外部带入的为准。最后获取 server 的版本跟配置里的版本进行比较,如果当前 server 的版本在配置里面存在,则说明这个版本是灰度的版本,不能被转发,直接过滤掉。
IP 端口判断的方式也是一样的,这是在网关中的处理方式,在内部服务中也是一样的处理方式,我这边为了方便就将代码复制了一份过去,大家可以进行简化,抽出来共用。如果我们的 article-service 需要发布新的版本,在发布之前会将元数据中的版本进行升级,然后在配置中心指定这个版本为灰度的版本,这样重新发布后正常请求就不会请求到这个灰度的服务。
The text was updated successfully, but these errors were encountered: