1
头图

简介: 本文介绍了微服务治理下金丝雀发布的能力,解决了发布期间少量流量验证新功能的问题。
前言
本文,我们继续聊聊《揭秘大流量场景下发布如丝般顺滑背后的原因》中的另外一环,灰度发布,也叫金丝雀发布。

很多互联网公司在半夜发布的另外一个重要原因是不具备可灰度能力,新版本存在 bug 或者其它原因会影响线上的客户,无奈之下只能选择在半夜进行发布来减少影响面。

我们知道默认情况下,无论是 Kubernetes 还是 ECS,新老版本都存在的情况下会根据特定的负载均衡算法随机地路由到不同的实例上,随机意味着出问题也会随机出现。我们需要一套动态路由来完成灰度发布的解决方案。

在 RPC 领域,我们称灰度发布为动态路由,动态路由的意思是指流量可以动态地路由到指定的实例上。

动态路由场景
动态路由是微服务里非常核心的功能,流量动态路由意味着可以做非常多的事情。由此衍生出各个场景:

金丝雀发布:只有满足特定规则(比如 Query Parameter、HEADER、COOKIE 中某些 KEY 满足一些条件)或者是固定流量比例的流量才会进入新版本,其它流量都路由到老版本上。
image.png

同机房优先路由:当公司规模扩大之后,应用会跨机房部署来达到高可用的目的。由于异地跨机房调用出现的网络延迟问题,需要确保服务消费方能优先调用相同机房的服务消费方,这就需要同机房优先路由的能力。
image.png

标签路由:金丝雀发布的新场景。金丝雀发布一般只有新和老两个版本,标签路由可以在线上部署多个版本,每个版本都对于一个标签。

全链路灰度:在业务比较复杂,服务调用链路较长的场景下,每个应用都需要设置路由规则会显得非常繁琐,全链路灰度在金丝雀/标签路由的基础上加上了 "标签透传" 的能力,让灰度流量只在灰度版本之间路由。

image.png

接下来我会分几篇文章详细讲一下这几个场景,今天我们先来聊聊金丝雀发布。金丝雀发布可以让我们在白天流量高峰喝着茶吃着瓜子进行线上发布,不需要在半夜为发布的事情而苦恼。

大流量下的应用部署现状
应用 Demo
Demo 以 Spring Cloud 为例,服务调用链路如下图所示:

image.png

流量从 Netflix Zuul 对应的 Ingress 进来,会调用 SC-A 应用对应的服务,SC-A 应用内部调用 SC-B 应用的服务,SC-B 应用内部调用 SC-C 应用的服务。SC-A 有线上版本和灰度版本这两个版本。

Helm 部署 Demo
Demo 为纯开源 Spring Cloud 架构,项目地址:https://github.com/aliyun/ali...

部署完毕后,阿里云容器服务上的工作负载情况如下:

image.png

我们通过 "while true; do curl http://{ip:port}/A/a;echo;done" shell 命令去执行,这个时候调用 SC-A 全部返回线上版本的 IP:

while true; do curl http://{ip:port}/A/a;echo;done
A[10.0.0.73] -> B[10.0.0.180] -> C[10.0.0.72]
A[10.0.0.73] -> B[10.0.0.180] -> C[10.0.0.72]
A[10.0.0.73] -> B[10.0.0.180] -> C[10.0.0.72]
A[10.0.0.73] -> B[10.0.0.180] -> C[10.0.0.72]
A[10.0.0.73] -> B[10.0.0.180] -> C[10.0.0.72]
...
设置金丝雀路由规则
我们在 MSE 上的应用详情页里的金丝雀 Tab 页里设置 HEADER 里 env 这个 KEY 的值为 test 的金丝雀路由条件:

image.png

传入 HEADER 继续使用 shell 执行:

while true; do curl -H "env:test" http://139.196.200.40/A/a;ech...
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
A1[10.0.0.20] -> B[10.0.0.180] -> C[10.0.0.72]
...
这个时候我们发现满足金丝雀规则的流量都去了 SC-A 的灰度版本。

金丝雀路由规则解析
大家看到金丝雀路由规则界面上有两种分别,分别是流量比例和流量规则:

image.png

流量规则:表示满足该规则的流量会路由到对应标签(本文使用 blue 作为灰度标签)实例上。比如本文例子中 HEADER 里 env=test 的流量一定会去 blue 标签对应的实例。

流量比例:不满足任何流量规则的流量会按照流量百分比进行路由。比如本文例子中不满足 HEADER 里 env=test 的流量会以 100% 的规则路由到未打标的实例上,由于是 100%,所以那些不满足规则的流量全部都去了未打标实例上(本文未打标表示线上版本)。

MSE 提供的流量规则里的条件支持 HEADER、Query Parameter、COOKIE 以及 Request BODY。

Query Parameter、HEADER、COOKIE 和 Request Body 除了支持常规的运算符外,还支持 in(白名单),对 100 取模和百分比。这里的百分比并不是比例规则中的总流量百分比,而是指对应参数的 hash 值取模,这样就可以让固定的值永远满足路由条件(如果按照流量比例,用户 A 这次访问的是线上版本,下次可能会访问灰度版本)。举个例子,如果 HEADER 中带有用户 ID,我让想部分用户永远能够访问灰度实例,这个时候可以对用户 ID 的 hash 值取模去完成(当然,这个也可以通过白名单去操作,白名单的缺点并不随机,需要输入各个名单)。

Request Body 目前支持解析 json 字符串,比如如下字符串:

{
"a": "aa",
"b": [

1,2,3

],
"c": [

{
  "d": "dd"
}

],
"e": {

"f": "ff"

}
}
JSON 访问表达式 .a 的值为 aa。
JSON 访问表达式 .b[0] 的值为 1。
JSON 访问表达式 .c[0].d 的值为 dd。
JSON 访问表达式 .e.f 的值为 ff。

总结
本文介绍了微服务治理下金丝雀发布的能力,解决了发布期间少量流量验证新功能的问题。您的应用只需接入 MSE 服务治理,无需任何操作即可享受到动态路由的能力。除了 MSE(微服务引擎),金丝雀发布还被 EDAS、SAE 等云产品集成。
原文链接
本文为阿里云原创内容,未经允许不得转载。


数据库知识分享者
27.8k 声望35.7k 粉丝

数据库知识分享