首页 > 其他分享 >无忧微服务:如何实现大流量下新版本的发布自由

无忧微服务:如何实现大流量下新版本的发布自由

时间:2024-03-28 15:26:49浏览次数:29  
标签:服务 无忧 流量 下新 灰度 版本 链路 下线 无损

作者:项良、十眠

微服务上云门槛降低,用好微服务才是关键

据调研数据显示,约 70% 的生产故障是由变更引起的。在阿里云上的企业应用如茶百道、极氪汽车和来电等,他们是如何解决变更引起的稳定性风险,实现了在白天高流量情况下应用发布平滑无损。今天我们将揭开阿里云微服务全链路无损发布解决方案的面纱, 快来一起参与探讨,并动手实践吧。

随着微服务开源以及生态的成熟,大大地推进了微服务技术的标准化。下图是展示单体和微服务架构选型的图,其中横坐标代表的是系统复杂度,纵坐标代表着效率,绿色曲线代表着单体架构,蓝色曲线代表微服务架构。我们可以看到随着系统复杂度的升高,单体架构跟微服务之间选型存在着一个拐点,拐点向右更适合选型微服务架构。随着微服务技术的标准化,意味着微服务上云的门槛也大幅度降低,他们之间选型的拐点也在持续地左移,采用微服务架构的企业日益增多。当企业开始大规模推广使用微服务时,如何用好、用稳微服务成为了大家关注的点,用好微服务的关键就是稳定性跟效率。

微服务变更风险大,发布被迫选择半夜

我们来一起看下一些客户真实的诉求,某茶饮企业变更引起事故占比一度超过 60%,每次发版都要避开高峰,在凌晨发版;某新能源企业业务连续性要求非常高,核心服务需要 7*24 小时持续在线,但是业务快速发展又需要保证迭代的效率,为了保证业务的稳定性,只能在业务低峰期即凌晨进行发布;同样,某科技公司因为缺少线上灰度能力,每次发布全量发布会导致影响面不可控,存在一定风险。

据调研数据称,70% 的生产故障都是由于变更导致的,除应用本身问题外,运行时风险概括为:不确定流量、不稳定调用、不稳定基础设施。今天,我们聊的解决方案就是为了全面消除变更态风险,解决用户生产变更态的稳定性风险。

我们先来分析一下,为什么微服务应用不能白天发布?因为相比于单体应用来说,微服务架构本身就是复杂的拓扑网络状的调用跟依赖结构。那么就意味着如果我们的微服务应用没有处理好上下线有损的问题,那么我们的任一微服务在发布的过程中都会存在短暂的服务不可用的情况,短时间内会出现大量的异常,导致业务受损。

最直观的感受就是我们一不小心点击了某个应用的重新部署,然后报警群里就会收到大量订单成功率下跌的告警,想想就很吓人。其次,发布时整个功能上线到线上的最后一个环节,一些在设计、研发、测试过程中累计下来的问题,在最后发布的环节才会触发。如果发布涉及到多个应用,如何进行合理发布,并且不会因为版本的问题而导致流量损失?我们总不希望看到,同一个用户在下单页面时候访问到新的版本,到支付阶段又碰到了老版本。

左下图是我拿开源 Spring Cloud 应用进行压测,并且在压测过程中重启应用后,整体压测请求的表现,我们可以看到有大量的异常。再进一步想一下,如果此时是生产系统,并且在白天大流量的场景下,极小的问题都会由于大流量的因素被快速放大,影响面难以控制。所以很多企业跟业务团队,宁愿选择在凌晨进行发布。

MSE 微服务全链路无损发布方案,消除变更风险

如何彻底解决变更稳定性问题?那就介绍今天的主角,MSE 微服务全链路无损发布方案。

我们分别从两个角度来分析问题:

  1. 如果我们新版本的代码没任何问题,服务上下线过程还是会有损,应该怎么解决?

  2. 如果我们新版本的代码有问题,那么我们如何控制问题的影响面?

首先,代码没问题,为什么上下线的环节中流量会有损失。当我们的微服务提供者下线后,服务的消费者无法实时感知节点下线,持续调用已经下线的节点地址,那么流量就会出现持续的报错;如果服务提供者在下线的过程中,请求执行到一半时,应用节点就直接停止了,那么就会导致在途请求以及处理中的请求失败,严重时还会导致线上的数据不一致;同样,在应用上线环节中也会有许多问题,比如新启动的节点如果没有完成预热,就直接承受打流量,那么就会导致新启动的节点直接被打垮,更有严重情况下,大流量场景下服务扩容都扩不出来。同样,微服务体系的生命周期没有跟 K8s 维度的 Readiness/Liveness 生命周期没有对齐,那么在发布的过程中会出现没对齐而导致的请求异常。

如果新版本的代码存在问题,那我们希望在发布新版本的过程中尽可能地控制影响面,阿里巴巴安全生产最佳实践告诉我们,在发布变更的过程中需要做到安全生产三板斧,即可灰度、可观测、可回滚。可灰度就是通过灰度的方式控制问题的影响面,如果我们业务代码新版本存在 bug,大多数情况下我们只能选择在业务低峰期(凌晨)进行发布;在微服务架构下,灰度发布需要做到全链路灰度的能力,目前开源自建很难实现全链路灰度的能力,如果出现流量丢标的情况,会导致灰度流量打到生产环境,引入了额外不可控的风险;可回滚,要求我们在出问题后,需要快速恢复止血,但如果没有一套完整的回滚方案与策略,回滚速度慢或者在回滚过程中引入更大的问题都是不可接受的。

如何解决微服务上下线过程流量有损问题

如果新版本代码没问题,如何解决服务上下线过程中流量有损的问题?

减少不必要的 API 报错,是最好的用户体验,也是最好的微服务开发体验。如何解决这个在微服务领域内让人头疼的问题呢。在这之前我们先来了解一下为什么我们的微服务在下线的过程中会有可能出现流量损失的问题。

原理分析:无损下线

如上图右侧所示,是一个微服务节点下线的正常流程。

  1. 下线前,消费者根据负载均衡规则调用服务提供者,业务正常。

  2. 服务提供者节点 A 准备下线,先对其中的一个节点进行操作,首先是触发停止 Java 进程信号。

  3. 节点停止过程中,服务提供者节点会向注册中心发送服务节点注销的动作。

  4. 服务注册中心接收到服务提供者节点列表变更的信号后会,通知消费者服务提供者列表中的节点已下线。

  5. 服务消费者收到新的服务提供者节点列表后,会刷新客户端的地址列表缓存,然后基于新的地址列表重新计算路由与负载均衡。

  6. 最终,服务消费者不再调用已经下线的节点。

微服务下线的流程虽然比较复杂,但整个流程还是非常符合逻辑的,微服务架构是通过服务注册与发现实现的节点感知,自然也是通过这条路子实现节点下线变化的感知。

参考我们这边给出的一些简单的实践数据,我想你的看法可能就会变得不同。从第 2 步到第 6 步的过程中,Eureka 在最差的情况下需要耗时 2 分钟,即使是 Nacos 在最差的情况下需要耗时 50 秒;在第 3 步中,Dubbo 3.0 之前的所有版本都是使用的是服务级别的注册与发现模型,意味着当业务量过大时,会引起注册中心压力大,假设每次注册/注销动作需要花费 20~30ms,五六百个服务则需要注册/注销花费掉近 15s 的时间;在第 5 步中, Spring Cloud 使用的 Ribbon 负载均衡默认的地址缓存刷新时间是 30 秒一次,那么意味着及时客户端实时地从注册中心获取到下线节点的信号,依旧会有一段时间客户端会将请求负载均衡至老的节点中。

如上图左侧所示,只有到客户端感知到服务端下线并且使用最新的地址列表进行路由与负载均衡时,请求才不会被负载均衡至下线的节点上。那么在节点开始下线的开始到请求不再被打到下线的节点上的这段时间内,业务请求都有可能出现问题,这段时间我们可以称之为服务调用报错期。

通过对微服务下线的流程分析,我们理解了解决微服务下线问题的关键就是:保证每一次微服务下线过程中,尽可能缩短服务调用报错期,同时确保待下线节点处理完任何发往该节点的请求之后再下线。

那么如何缩短服务调用报错期呢?我们想到了一些策略:

  1. 将步骤 3 即节点向注册中心执行服务下线的过程提前到步骤 2 之前,即让服务注销的通知行为在应用下线前执行,考虑到 K8s 提供了 Prestop 接口,那么我们就可以将该流程抽象出来,放到 K8s 的 Prestop 中进行触发。

  2. 如果注册中心能力不行,那么我们是否有可能服务端在下线之前绕过注册中心直接告知客户端当前服务端节点下线的信号,该动作也可以放在 K8s 的 Prestop 接口中触发。

  3. 客户端在收到服务端通知后,是否可以主动刷新客户端的地址列表缓存。

如何尽可能得保证服务端节点在处理完任何发往该节点的请求之后再下线?站在服务端视角考虑,在告知了客户端下线的信号后,可以提供一种等待机制,保证所有的在途请求以及服务端正在处理的请求被处理完成之后再进行下线流程。

实战演练:缩容过程中无损下线的表现

下面我们就通过一个实践来看看无损下线的效果与表现:

该实践分为四个步骤,首先我们在 ACK 控制台配置定时伸缩任务,模拟应用扩缩容的场景,我们可以配置 5 分钟内第 2 分钟扩容,第 4 分钟缩容;第二步,应用接入 MSE 服务治理后默认会具备无损下线能力,我们需要将基线环境增加环境变量关闭无损下线能力,作为对照组;灰度环境接入 MSE 服务治理后,不做任何操作,即默认开启无损下线能力,作为实验组;第三步,我们同时发起基线跟灰度的流量,观察其表现;第四步,我们在 MSE 应用详情的 QPS 数据模块中可以看出,未打标环境(关闭无损下线的应用)在扩缩容过程中出现了 99 个异常,然而灰度环境则无任何错误数。

标签:服务,无忧,流量,下新,灰度,版本,链路,下线,无损
From: https://www.cnblogs.com/alisystemsoftware/p/18101744

相关文章

  • 编译opencv: cmake编译opencv,不带版本号
    在Linux上使用cmake编译OpenCV,默认都是协议版本号的,一般会生成三个文件,一个so和两个软链接。在部分系统上移植的时候,软链接会成问题,所以需要重新编译OpenCV,解决软链接的问题。 我是使用cmake编译的,所以需要修改【OpenCVModule.cmake】文件文件位置:【opencv-4.8.0】-【cmake......
  • ubuntu16.04server版本安装网卡
    设置用户开机进入BIOS里取消勾选SecureBootEnableci30#输入用户名和密码登陆sudopasswdroot#如果是首次登陆,需要设置root密码(密码统一设置123456)su#切换root用户,输入root用户密码安装make工具:fdisk-l#查看安装磁盘为/dev/sdb1mount/dev/sdb1/opt......
  • sfc命令参数 扫描所有保护的系统文件的完整性,并使用正确的 Microsoft 版本替换 不正确
    sfc/?Microsoft(R)Windows(R)ResourceChecker6.0版版权所有(C)MicrosoftCorporation。保留所有权利。扫描所有保护的系统文件的完整性,并使用正确的Microsoft版本替换不正确的版本。SFC[/SCANNOW][/VERIFYONLY][/SCANFILE=<file>][/VERIFYFILE=<file>] ......
  • 最新AI创作系统/ChatGPT商业运营版网站程序源码,支持ai绘画(MJ),支持GPT4,实时语音识别输入
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录目录文章目录前言一、系统更新日志二、功能总结前言最新AI创作系统/ChatGPT商业运营版网站程序源码,支持ai绘画(MJ),支持GPT4,实时语音识别输入,免费更新版本一、系统更新日志最新更......
  • vivo 消息中间件测试环境项目多版本实践
    作者:vivo互联网中间件团队-LiuTao在开源RocketMQ基础之上,关于【测试环境项目多版本隔离】业务诉求的落地与实践。一、背景在2022年8月份vivo互联网中间件团队完成了互联网在线业务的MQ引擎升级,从RabbitMQ到RocketMQ的平滑升级替换。在业务使用消息中间件的过程中......
  • 部署elementPlus离线版本
    最近项目需要离线开发,不能联网查一些组件的api,于是决定搞一个离线版的文档一、下载官方文档下载地址github地址gitee地址选择版本直接下载压缩包二、下载live-server插件全局下载live-server插件npmilive-server-gvscode下载三、运行在文件目录下......
  • ActiveMQ Artemis 系列| High Availability 主备模式(消息复制) 版本2.33.0
    一、ActiveMQArtemis介绍ApacheActiveMQArtemis是一个高性能的开源消息代理,它完全符合JavaMessageService(JMS)2.0规范,并支持多种通信协议,包括AMQP、MQTT、STOMP和OpenWire等。ActiveMQArtemis由ApacheSoftwareFoundation开发和维护,旨在提供可靠的消......
  • linux安装/切换不同版本c/c++
    查看ubuntu系统上g++的版本:ls/usr/bin/g++*安装指定版本gcc和g++#以version==4.9为例sudoapt-getinstallgcc-4.9g++-4.9切换不同版本当ubuntu系统上安装了不同版本的gcc和g++,可以使用update-alternatives命令设置默认使用哪个版本,典型的如在Ubuntu16.04里安......
  • 强力工具(欢迎fork):Java版本的Sybase ASE ISQL命令行
    \1.背景曾经,经常遇到有人问,Sybase(ASE,国内基本上把以前的SybaseASE数据库简称为Sybase数据库,现在官方已经叫做SAPASE,在我看来无所谓。只要大家知道它是哪个数据库就行了。)数据库有没有短小点的命令行工具。我说,昨个短小法?SybaseASE确实自带一个isql命令行,功能也很......
  • 2024最新梦想贩卖机,变现宝知识付费小程序(修改版本+前后端)
    想贩卖机升级版,变现宝吸取了资源变现类产品的很多优点,摒弃了那些无关紧要的东西,使本产品在运营和变现能力上,实现了质的超越。多领域素材资源知识变现营销裂变独立版。实现流量互导,多渠道变现。独立部署,可绑自有独立域名不限制域   网盘下载链接:https://47.95.205.7/?p......