灰度发布(Gray Release,也称为灰度发布或金丝雀发布)是指在软件或服务发布过程中,将新版本的功能或服务以较小的比例引入到生产环境中,仅向部分用户或节点提供新功能的一种发布策略。
在传统的全量发布中,新版本的功能会一次性全部部署到所有的用户或节点上。然而,这种方式潜在的风险是,如果新版本存在缺陷或问题,可能会对所有用户或节点产生严重的影响,导致系统崩溃或服务不可用。
相比之下,灰度发布采用较小的规模,并逐步将新版本的功能引入到生产环境中,仅向一小部分用户或节点提供新功能。通过持续监测和评估,可以在发现问题时及时回滚或修复。这种逐步引入新版本的方式可以降低风险,并提高系统的稳定性和可靠性。
1、实现思路
灰色发布的常见实现思路有以下几种:
- 根据用户划分:根据用户标识或用户组进行划分,在整个用户群体中只选择一小部分用户获得新功能。
- 根据地域划分:在不同地区或不同节点上进行划分,在其中的一小部分地区或节点进行新功能的发布。
- 根据流量划分:根据流量的百分比或请求次数进行划分,只将一部分请求流量引导到新功能上。
而在生产环境中,比较常用的是根据用户标识来实现灰色发布,也就是说先让一小部分用户体验新功能,以发现新服务中可能存在的某种缺陷或不足。
2、具体实现
Spring Cloud 全链路灰色发布的关键实现思路如下图所示:
灰度发布的具体实现步骤如下:
- 前端程序在灰度测试的用户 Header 头中打上标签,例如在 Header 中添加“grap-tag: true”,其表示要进行灰常测试(访问灰度服务),而其他则为访问正式服务。
- 在负载均衡器 Spring Cloud LoadBalancer 中,拿到 Header 中的“grap-tag”进行判断,如果此标签不为空,并等于“true”的话,表示要访问灰度发布的服务,否则只访问正式的服务。
- 在网关 Spring Cloud Gateway 中,将 Header 标签“grap-tag: true”继续往下一个调用服务中传递。
- 在后续的调用服务中,需要实现以下两个关键功能:
- 在负载均衡器 Spring Cloud LoadBalancer 中,判断灰度发布标签,将请求分发到对应服务。
- 将灰度发布标签(如果存在),继续传递给下一个调用的服务。
经过第四步的反复传递之后,整个 Spring Cloud 全链路的灰度发布就完成了。
3、核心实现思路和代码
灰度发布的关键实现技术和代码如下。
(1)区分正式服务和灰度服务
在灰度发布的执行流程中,有一个核心的问题,如果在 Spring Cloud LoadBalancer 进行服务调用时,区分正式服务和灰度服务呢?
这个问题的解决方案是:在灰度服务既注册中心的 MetaData(元数据)中标识自己为灰度服务即可,而元数据中没有标识(灰度服务)的则为正式服务,以 Nacos 为例,它的设置如下:
(2)负载均衡调用灰度服务
Spring Cloud LoadBalancer 判断并调用灰度服务的关键实现代码如下:
以上代码为自定义负载均衡器,并使用了轮询算法。如果 Header 中有灰度标签,则只查询灰度服务的节点实例,否则则查询出所有的正式节点实例(以供服务调用或服务转发)。
(3)网关传递灰度标识
要在网关 Spring Cloud Gateway 中传递灰度标识,只需要在 Gateway 的全局自定义过滤器中设置 Response 的 Header 即可,具体实现代码如下:
(4)Openfeign 传递灰度标签
HTTP 调用工具 Openfeign 传递灰度标签的实现代码如下:
小结
灰度发布是微服务时代保证生产环境安全的必备措施,而其关键实现思路是:
- 注册中心区分正常服务和灰度服务;
- 负载均衡正确转发正常服务和灰度服务;
- 网关和 HTTP 工具传递灰度标签。
这样,我们就完整的实现 Spring Cloud 全链路灰度发布功能了。