打造更稳定的 Serverless 业务 | D2 分享视频+文章

Hi,大家好,在 2020.12 月的 D2,我为大家做了一场紧凑的微分享,话题为《打造更稳定的 Serverless 业务》。时间关系,大约只有 20 分钟,为在 Serverless 世界中踟躇的同学们抛砖引玉,让大家了解下我们在做什么。

从大促说起

除了开发和维护 MidwayJS 这一框架体系,提供应用、函数、一体化解决方案外,我们也在 Serverless 的 Runtime 层面有所涉猎。

在 2020 年,我们开放了 Midway Serverless 框架和一体化方案,弥补了 Midway 在 Serverless 方面的缺失,也朝着多场景框架又迈出了一步。

除了社区,阿里内部的 Serverless 业务也蓬勃发展,淘系,飞猪,考拉,高德等 BU 的业务都已经扬帆起航,整体达到规模比去年增长了 10 倍,承接的流量也比同期翻了 6 倍,可以说,Node.js Serverless 已经真正的站稳了脚跟,和原有的 Node.js 应用体系共同支撑起了阿里的前端业务。

高德也在” 十一出行节 “再创新记录,提前达到了目标。

稳定性保障

去年这个时期,我们 Node.js Serverless 还处在一个起步的阶段,还在做研发保障,平台基建的事情。经历了去年的 ”研发模式升级“ 战役之后,整个发布平台,构建体系,以及开发、调试的能力都经过了重塑,已经达到了可以研发业务上线的要求。

随着使用 BU 的不断增多,业务对稳定性也提出了更高的要求,这迫使我们对此需要提供更多的能力。” 稳定性 “就是随之而来的最大的考验。

对此,我们在 2020 年大促做好了大考准备。针对双促,除了传统的压测,盘点之外,今年由于加入了 Serverles 场景,额外增加了针对 Node.js Serverless 的稳定性保障。

整个额外保障分为如下三块,我们将一一阐述。

强弱依赖分析

第一块是强弱依赖分析。利用 技术手段 将业务调用的下游依赖分析出来,明明白白的展示给业务开发,让其清楚的知道,哪些是 ” 强依赖 “,哪些是 ” 弱依赖 “。

所谓的强依赖,是业务直接依赖的下游,如果该下游出现问题,会直接反应到业务本身,造成不可预估的影响,而弱依赖,则是下游出现问题,业务本身不影响或者只影响少许。

如图上的业务依赖,当业务 B 出现问题,依赖 C 包含了一部分业务 B 的数据,业务 A 的系统可以继续稳定的运行,这样子业务 B 对于业务 A 来说就是一个 ”弱依赖”,而业务 C 则是一个强依赖(单条链路)。

当然这是一个理想情况,业务本身会相对复杂,数据接口可能业务非常繁杂,随着时间的推移,还会经常更新迭代,无法人肉沉淀。

这个时候,我们使用了一种依赖分析手段,这套技术,是监控的副产物,由 Alinode 提供的底层带来的能力,详细不久大家就会看到一个全新的 Alinode。

Ainode 是阿里 Node.js 架构组维护的 Node.js 运行时,在社区的 Node.js 运行时之上提供了一系列监控、诊断优化能力。

在拿到强弱依赖之后,我们会推进业务的改进,当然,这个改进本质上是一个自我梳理的过程, 并不一定 需要把强依赖都变成弱依赖 ,是一个降低业务依赖风险的过程。

改进的方法也有不少,比如把数据降级,加缓存,或者增加新的数据源,做好不同的数据隔离和错误处理等等。

流量模型预估

第二块是流量模型的预估。

传统的流量模型是“流量(QPS + 机器数)的评估,在 Serverless 场景下,情况以然不同,这里主要有两点情况:

  • 1、容器的数量对业务来说可能已经不太关心,业务希望只需要提供总流量就可以上线

  • 2、平台的单容器承载单位为并发数,这不符合平常业务的换算单位

这导致了开发很难一次性将业务上线,需要 额外关心单个容器,能够承载多少流量 ,然后再将流量和并发度进行转换,这个过程很容易出错且不高效。

这一层的含义是,对已知的流量做预估,而不是未知的流量。比如抢红包,是每个整点,那么每个整点的流量可能会有新高,真个流量就是已知的流量。未知的突然流量,是不应该被允许到达业务代码,尽可能在网关层之前就被拦截掉。

针对已经的流量,如何反向预估需要多少资源消耗,虽然用户不关心,但是我们的平台侧上线时还是需要计算,并给出推荐的值,这其中有两个方式。

一是计算出单个容器在单一接口符合业务要求的情况下,比如满足 RT 要求,计算出单容器合理的 QPS 和并发度,这个时候,我们已经可以拿这个值去设置函数的单容器并发以及容器数。

二是通过网关,在业务上线引入流量的时候进行流量测算,是否真的满足上述的场景,根据实际的流量,我们可以动态的调整预留的实例数和弹性的实例比率,以达到最佳的资源配比。

并发度测算是基于”拥塞控制算法”来得出的,整套产品需要配套平台基建来做,后续我们会针对这个方案进行更细致的分享,欢迎关注 MidwayJS。

多层流量管控

前两项其实都是在业务上线前做的,而流量管控,则是运行时层面实时的处理。

在一般的场景下,我们有多个网关来管理所有的流量。以阿里内部为例,我们有两层网关,分别为通用网关和函数特有的网关,其之下,则是函数容器本身。

当流量来临时,先经过通用网关,路由到函数网关,再根据域名和路径,从函数网关查询特定的函数信息,将流量打入函数。

每一层都需要一定的流量管控。在特定的场景下,经过通用网关的流量是相对较大的(由于函数的数量不定,且为弹性),通用网关的流量限制一般为函数网关所能经过的最大流量。

当流量到达函数网关时,网关才会相应的去计算到达函数的流量,进行更细粒度的流量控制。而函数网关层面的流量管控,指的则是面向单一函数容器(或是单一函数业务)的限制。

在函数网关的流量管控中,着重是希望将特定的流量打入到特定的函数中,防止不同的函数,使用不同的功能。

而在函数容器本身,我们还做了第三道防护,除了第二点的流量测算外,额外还有防雪崩的作用。

所谓的防雪崩,是防止当一个(或者多个)容器无法工作,所有流量打到其他容器,导致其他容器批量无法工作的情况。

在每个容器都做了这样的防护,才算是真正的将风险降到最低。

这是一个微分享,也是我们这一年来的一些在 Serverless 稳定性方面的总结。其实整个都是出现问题,到解决问题的思考过程,希望大家能够有所收获。

最后: