简介: 在业务初期,因人手有限,想要快速开发并上线产品,很多团队使用单体的架构来开发。但是随着公司的发展,会不断往系统里面添加新的业务功能,系统越来越庞大,需求不断增加,越来越多的人也会加入到开发团队,代码库也会增速的膨胀,慢慢的单体应用变得越来越臃肿,可维护性和灵活性逐渐降低,维护成本越来越高。
在业务初期,因人手有限,想要快速开发并上线产品,很多团队使用单体的架构来开发。但是随着公司的发展,会不断往系统里面添加新的业务功能,系统越来越庞大,需求不断增加,越来越多的人也会加入到开发团队,代码库也会增速的膨胀,慢慢的单体应用变得越来越臃肿,可维护性和灵活性逐渐降低,维护成本越来越高。
这个时候很多团队会把单体应用架构改为微服务的架构,解决单体应用的问题。但随着微服务越来越多,运维投入会越来越大,需要保证几十甚至几百个服务正常运行与协作,这给运维带来了很大的挑战,下面从软件生命周期的角度来分析这些挑战:
面对以上问题,Serverless 应用引擎在这方面都做了哪些工作?
如上图所示,Serverless 应用引擎(SAE)基于神龙 + ECI + VPC + SLB + NAS 等 IaaS 资源,构建了一个 Kubernetes 集群,在此之上提供了应用管理和微服务治理的一些能力。它可以针对不同应用类型进行托管,比如 Spring Cloud 应用、Dubbo 应用、HSF 应用、Web 应用和多语言应用。并且支持 Cloudtoolkit 插件、云效 RDC / Jenkins 等开发者工具。在 Serverless 应用引擎上,零代码改造就可以把 Java 微服务的应用迁移到 Serverless。
总的来说,Serverless 应用引擎能够提供成本更优、效率更高的一站式应用托管方案,零门槛、零改造、零容器基础,即可享受 Serverless + K8s + 微服务带来的技术红利。
=========
Serverless 应用引擎(SAE)基于 Alibaba CloudToolkit 插件+ 跳板机可以实现:
如上图所示,在实现的时候用户需要有一个 ECS 代理服务器,实际注册的是 ECS 代理服务器到 SAE 的注册中心,IDEA 在安装 Cloudtoolkit 插件以后,在启动进程时,会在本地拉起一个通道服务,这个通道服务会连上 ECS 代理服务器,本地所有的请求都会转到 ECS 代理服务器上,云端对服务的调用也会通过 ECS 代理转到本地,这样就可以以最新的代码在本地断点调试,这就是云端联调的实现。
代码在本地完成联调以后,要能快速地通过 Maven 插件和 IDEA-plugin,可以很快地一键部署到云端的开发环境。
=========
通过这三点可以让应用发布做到可灰度、可观测、可回滚。
在版本更换的过程中,SAE 是如何保证旧版本的微服务流量可以无损地下线掉?
上图是微服务注册和发行的整个流程,图中有服务消费者和服务提供者,服务提供者分别有 B1、B2 两台实例,服务消费者分别有 A1、A2 两台实例。
B1、B2 把自己注册到注册中心,消费者从注册中心刷新服务列表,发现服务提供者 B1、B2,正常情况下,消费者开始调用 B1 或者 B2,服务提供者 B 需要发布新版本,先对其中一个节点进行操作,如 B1,首先停止 Java 进程,服务停止过程又分为主动销毁和被动销毁,主动销毁是准实时的,被动销毁的时间由不同的注册中心决定,最差的情况可能需要一分钟。
如果应用是正常停止,Spring Cloud 和 Dubbo 框架的 ShutdownHook 能正常被执行,这一步的耗时基本上是可以忽略不计的。如果应用是非正常停止,比如说直接 Kill-9 的一个停止,或者是 Docker 镜像构建的时候,Java 进程不是一号进程,且没有把 Kill 信号传递给应用的话,那么服务提供者不会主动去注销节点,它会等待注册中心去发现、被动地去感知服务下线的过程。
当微服务注册中心感知到服务下线以后,会通知服务消费者其中一个服务节点已下线,这里有两种方式:注册中心的推送和消费者的轮巡。注册中心刷新服务列表,感知到提供者已经下线一个节点,这一步对于 Dubbo 框架来说不存在,但对于 Spring Cloud 来说,它最差的刷新时间是 30 秒。等消费者的服务列表更新以后,就不再调用下线节点 B。从第 2 步到第 6 步的过程中,注册中心如果是 Eureka,最差的情况需要消耗两分钟;如果是 Nacos,最差的情况需要消耗 50 秒。
在这个时间内请求都有可能出现问题,所以发布的时候会出现各种报错。
经过上面的分析,在传统的发布流程中,客户端有一个服务端调用报错期,这是由于客户端没有及时感知到服务端下线的实例造成的,这种情况主要是因为服务提供者借助微服务,通知消费者来更新服务提供的列表造成的。
那能否绕过注册中心,服务提供者直接通知服务消费者?答案是肯定的。SAE 做了两件事情,第一,服务提供者在应用发布前,会主动向服务注册中心注销应用,并将应用标记为已下线状态,将原来停止进程阶段的注销变成了 preStop 阶段注销进程。
在接收到服务消费者的请求时,首先会正常处理本次请求,并且通知服务消费者此节点已经下线,在此之后消费者收到通知后,会立即刷新自己的服务列表,在此之后服务消费者就不会再把请求发到服务提供者 B1 的实例上。
通过上面这个方案,就使得下线感知时间大大缩短,从原来的分钟级别做到准实时的,确保你的应用在下线时能够做到业务无损。
发布策略分为分批发布和灰度发布,如何实现流量的灰度?从上面的架构图中可以看到,在应用发布之前,要配置一个灰度规则,比如按 uid 的取模余值 =20 来作为灰度流量的规则,当应用发布的时候,会对已发布的节点标识为一个灰度的版本,在这样的情况下,当有流量进来时,微服务网关和消费者都会通过配置中心拿到在治理中心配置的灰度规则。
消费者的 Agent 也会从注册中心拉取它所依赖的服务的一些信息,当一个流量进到消费者时,会按照灰度规则来做匹配,如果是灰度的流量,它会转化到灰度的机器上;如果是正常流量,它会转到正常的机器上,这是基于标签实现的灰度发布的具体逻辑。
=========
运行态的实例,服务的运行过程中会出现这样或者那样的问题,怎么去排查和解决它?
排查和解决的前提是必须具有强大的应用监控能力和诊断能力,SAE 集成了云产品 ARMS,能够让跑在上面的 Java 微服务看到应用的调用关系拓扑图,可以定位到你的 MySQL 慢服务方法的调用堆栈,进而定位到代码级别的问题。
比如一个请求响应慢,业务出现问题,它可以定位到是哪个请求、哪个服务、服务的哪行代码出现了问题,这样就能为解决问题带来很多便利。总的来说,就是我们要先有监控报警的能力,才能帮助我们更好地诊断服务运营过程中的问题。
上面说到我们通过监控、报警来排查、解决遇到的问题,那我们的系统能否主动去做一些事情呢?SAE 作为一个 Serverless 平台,具备很多自运维的能力,下图中有两个场景:
面对这种情况,SAE 提供了服务治理能力,即离群摘除,它可以配置,当网络超时严重或者后端服务 5xx 报错达到一定比例时,可以选择把该节点从消费端服务列表中摘除,从而使得有问题的机器不再响应业务的请求,很好地保证业务的 SLA。
这种情况下,通过 SAE 这种 Serverless 应用引擎,节点在配置健康检查以后,节点里的容器是可以重新拉起的,可以做到快速对进程进行恢复。
基于 Serverless Paas 平台 SAE 和其他产品的互动,来达到整个运维态的闭环。
用户在使用的时候,可以运用 PTS 压测工具构造场景,然后得出来一些阈值。比如可以对流量高峰所需要消耗的资源进行预估,这时就可以根据这些阈值设计弹性策略。当业务系统达到请求比例时,就可以按照所设置的弹性策略来扩缩容自己的机器。
扩缩容在时间上,有可能还跟不上处理大批量的请求,这时可以通过和 AHAS 的互动,配置限流降级的能力。当有突发大流量时,首先可以用 AHAS 的能力把一些流量挡在门外,然后同时触发 SAE 上应用的扩容策略去扩容实例,当这些实例扩容完成之后,整个机器的平均负载会下降,流量又重新放进来。从突发大流量到限流降级再到扩容,最后到流量达到正常状态,这就是“精准容量+限流降级+极致弹性”的最佳实践模型。
本文首先按照提出问题、解决问题的思路,阐述微服务在开发、发布和运行态是如何解决问题的;再介绍如何通过 Serverless 产品和其他产品的互动,从而实现精准流量、限流降级和极致弹性。
王科怀,花名:行松,阿里云 SAE 技术研发,负责 SAE 产品 Runtime 层技术架构设计,专注于微服务、Serverless、应用托管领域,基于云原生技术持续打造新一代应用托管平台。
原文链接
本文为阿里云原创内容,未经允许不得转载