关于SegmentFault:大流量场景下如何云淡风轻地进行线上发布

7次阅读

共计 4605 个字符,预计需要花费 12 分钟才能阅读完成。

简介:本文介绍了微服务治理下金丝雀公布的能力,解决了公布期间大量流量验证新性能的问题。

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

咱们晓得默认状况下,无论是 Kubernetes 还是 ECS,新老版本都存在的状况下会依据特定的负载平衡算法随机地路由到不同的实例上,随机意味着出问题也会随机呈现。咱们须要一套动静路由来实现灰度公布的解决方案。

在 RPC 畛域,咱们称灰度公布为动静路由,动静路由的意思是指流量能够动静地路由到指定的实例上。

动静路由场景

动静路由是微服务里十分外围的性能,流量动静路由意味着能够做十分多的事件。由此衍生出各个场景:

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

  • 同机房优先路由:当公司规模扩充之后,利用会跨机房部署来达到高可用的目标。因为异地跨机房调用呈现的网络提早问题,须要确保服务生产方能优先调用雷同机房的服务生产方,这就须要同机房优先路由的能力。

  • 标签路由:金丝雀公布的新场景。金丝雀公布个别只有新和老两个版本,标签路由能够在线上部署多个版本,每个版本都对于一个标签。
  • 全链路灰度:在业务比较复杂,服务调用链路较长的场景下,每个利用都须要设置路由规定会显得十分繁琐,全链路灰度在金丝雀 / 标签路由的根底上加上了 “ 标签透传 ” 的能力,让灰度流量只在灰度版本之间路由。

接下来我会分几篇文章具体讲一下这几个场景,明天咱们先来聊聊金丝雀公布。金丝雀公布能够让咱们在白天流量顶峰喝着茶吃着瓜子进行线上公布,不须要在中午为公布的事件而苦恼。

大流量下的利用部署现状

利用 Demo

Demo 以 Spring Cloud 为例,服务调用链路如下图所示:

流量从 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…。

部署结束后,阿里云容器服务上的工作负载状况如下:

咱们通过 “while true; do curl http://{ip:port}/A/a;echo;done” shell 命令一直地去拜访 Spring Cloud 服务,各个服务的作用仅仅是打印以后服务的 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]
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]
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]
A1[10.0.0.20] -> 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]
A1[10.0.0.20] -> 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]
...

从这个过程咱们显著能够看出 Netflix Zuul -> SC-A 这条链路是随机拜访的,因为 SC-A 的线上版本和灰度版本各只有 1 个 Pod,所以随机打印了这两个 POD 的 IP。

开源金丝雀的实现

动静路由的实质就是寻址过程中去找符合条件的实例地址。

Apache Dubbo 提供了 RouterChain 的能力去过滤 Invoker 列表,RouterChain 外部保护着 Router 列表,每个 Router 都会做过滤 Invoker 的逻辑,最初将 Invoker 列表交付给 LoadBalance 做负载平衡获取最初的 Invoker。

ScriptRouter,ConditionRouter 和 TagRouter 这些内置的 Router 外部都是 Dubbo 自带的动静路由能力。

Spring Cloud 的路由能力由 Ribbon 实现。Ribbon 设计了 ILoadBalancer 接口用于获取 Server 列表,最初将这个列表交付给 IRule 做负载平衡策略获取最初的 Server。这块在设计上跟 Dubbo 相比是有缺点的。

Spring Cloud Ribbon 里的 ILoadBalancer 相当于是 Dubbo RouterChain 里的一个 Router,IRule 相当于是 Dubbo LoadBalance。

最新版本的 Spring Cloud 新增了 Spring Cloud LoadBalancer 组件代替 Ribbon 用于做负载平衡,Spring Cloud LoadBalancer 里的 ServiceInstanceListSupplier 用于获取实例列表信息,ReactiveLoadBalancer 应用负载平衡策略获取最初的实例。

这是 3 者对应组件的阐明:

Apache Dubbo 尽管内置了各种 Router,但理论应用下来却有十分多的问题。比方 TagRouter 跟 IP 绑定,在 Kubernetes 下无奈工作;ScriptRouter 用了 ScriptEngine 去做脚本的解决,会有性能问题;Dubbo Admin 的应用体验十分蹩脚等等。

Spring Cloud 官网并没有提供动静路由的能力,只有社区上的一些开发者本人去扩大了这个能力,社区上也没有任何的 UI 交互界面。

这时候 MSE 通知你,MSE 的微服务解决方案提供了动静路由的能力,不须要做任何的代码和配置的批改,就能应用 OPEN API 或者 UI 交互去实现金丝雀公布。只需将您的利用接入 MSE 服务治理,您就能享受到金丝雀能力。

只有你的利用是基于 Spring Cloud 或 Dubbo 最近五年内的版本开发,就能间接应用残缺的 MSE 微服务治理能力,不须要批改任何代码和配置。

无需任何代码批改就能够做到动静路由的能力,这不香吗?

MSE 金丝雀能力

利用接入 MSE 即可享受 MSE 提供的动静路由能力,无需任何代码批改。

引入标签概念

MSE 引入了标签的概念,能够针对每个标签设置路由规定,满足该路由规定的流量会路由到这个标签对应的实例下。咱们将 Spring Cloud Demo 进行一点革新,给 SC-A 的灰度版本打上 “blue” 标签(Helm 曾经实现了这个步骤)。

接入 MSE 后,MSE 默认会给利用调配一个 100% 路由到未打标实例的路由规定。此时,咱们持续通过 “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 的金丝雀路由条件:

传入 HEADER 持续应用 shell 执行:

while true; do curl -H "env:test" http://139.196.200.40/A/a;echo;done
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 的灰度版本。

金丝雀路由规定解析

大家看到金丝雀路由规定界面上有两种别离,别离是 流量比例 流量规定:

流量规定:示意满足该规定的流量会路由到对应标签 (本文应用 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 等云产品集成。

作者:中间件小哥
原文链接
本文为阿里云原创内容,未经容许不得转载

正文完
 0