作者|西流(阿里云技术专家)

背景

2019 年 Berkeley 预测 Serverless 将取代 Serverful 计算[1],成为云计算的计算新范式。Serverless 为应用程序开发提供了一种全新的系统架构,其凭借着弹性伸缩省事省心,按需付费更低成本、聚焦业务降低 OPS 这三大核心价值,将开发人员从繁重的手动资源管理和性能成本优化中解放出来,让工程师的生产力再次发生变革。

根据 CNCF 官方定义[2]:

Serverless is a cloud native development model that allows developers to build and run applications without having to manage servers. There are still servers in serverless, but they are abstracted away from app development. A cloud provider handles the routine work of provisioning, maintaining, and scaling the server infrastructure. Developers can simply package their code in containers for deployment. Once deployed, serverless apps respond to demand and automatically scale up and down as needed. Serverless offerings from public cloud providers are usually metered on-demand through an event-driven execution model. As a result, when a serverless function is sitting idle, it doesn’t cost anything.

从上面的定义可以看出, Severless != No Server, 只是对于开发者来说,没有了 Server 去管理。而在云厂商提供的服务中, Serverless 架构应该是采用 FaaS(Function as a service, 函数即服务)和 BaaS(后端服务)服务来解决问题的一种设计。

FaaS 服务的典型代表: AWS lambda、 阿里云函数计算 FC、Azure Functions、Google Cloud Functions 等

BaaS 服务典型代表: AWS: S3、Dynamodb、SQS 等; 阿里云: OSS、 TableStore、MNS 等



Serverless 计算

当然随着需求和技术的发展,业界出现了一些 FaaS 以外的其它形态的 Serverless 计算服务,比如 Google Cloud Run、AWS App Runner、阿里云 Serverless 应用引擎 SAE、 阿里云 Serverless Kubernetes ASK 等,这些服务也提供了弹性伸缩能力和按使用计费的收费模式,具备 Serverless 服务的形态,可以说进一步扩大了Serverless 计算的阵营。

而在 Serverless 计算领域最典型的两种产品形态代表 FaaS 和 Google Cloud Run, 都不约而同采用了并发度(Concurrency)这个指标作为扩缩容策略。接下来我们重点剖析下不同产品形态下并发的语义以及为什么这些流行的 Serverless 计算产品为什么采用并发度作为扩缩容的策略。

什么是并发?

并发是现代计算的核心原则之一, 并发是指计算系统同时处理多个任务的能力。例如,如果您的计算机同时运行多个程序,则具有多个并发进程/线程可以共享 CPU 时间。如果单个应用程序进程同时处理多个网络请求,或者并行处理队列中的多个作业,则也可以认为该应用程序正在执行并发工作。

比如 “世界第一语言 PHP” 在 Web 领域的实践,使用就是进程池,如下图中的 FastCGI 进程管理器。发送到服务器的 Web 请求将被分配给进程池中的 CGI 进程。该 CGI 进程将处理该单个请求。如果同时收到多个请求,则将启动多个 CGI 进程并行处理它们。然而,每个进程一次只能处理一个请求。服务器能够通过对 CGI 进程进行上下文切换来处理并发请求。操作系统调度程序将跟踪所有 CGI 进程,并在需要时切换正在 CPU 上运行的 CGI 进程,以使每个 CGI 进程在需要时都能获得属于自己的、公平的 CPU 时间份额。



PHP Web 运行原理图

如今,有更多用于并发的工具, 这包括现代编程语言内置的强大异步并发机制,以及帮助简化并发的云计算服务。让我们看看一些云计算服务如何设计和使用并发。

单实例单并发

云厂商的 FaaS 服务的并发扩缩容原理基本大同小异, 我们以 AWS Lambda 官方文档[3] 为参考:

当首次调用一个函数时,FaaS 服务会创建一个函数实例,并运行处理程序方法以处理事件。完成后,函数会在一段时间内保持可用状态,以处理后续的事件。如果在函数忙碌时有其他事件到达,FaaS 会创建更多的函数实例来同时处理这些请求。

从文档中我们可以看出,每个函数实例一次只能处理一个事件请求(即 one concurrent request per instance,也称为单实例单并发)。在处理事件请求时,函数被认为是繁忙的,因此任何并发事件都必须转到另一个函数实例。每次必须创建函数的新实例时,都会出现短暂的“冷启动”(Cold Start)延迟。这个冷启动的持续时间取决于您的代码大小和使用的运行时 Runtime。下图[4]显示了当有多个并发请求需要进行并行处理时,FaaS 如何实时扩展函数实例的数量:

Tips: 只有绿色部分是毫秒计费, 黄色和空白部分均不会计费, 真正100%为计算资源付费。



FaaS scaling and concurrency

这使得 FaaS 的并发模型在某些方面类似于那些老式的 PHP 进程管理器。在这两种情况下: 1). PHP 进程管理器通过并行启动更多进程来实现并发。单个进程一次只能处理一个事件请求。2). FaaS 通过并行启动更多的执行环境容器实例来实现并发, 单个实例一次只能处理一个事件请求。 但使用 PHP 进程管理器那样的进程级别的并发有两个经典难题需要解决:

  • 进程之间的安全隔离:您必须在操作系统分配 CPU 时间和系统资源给进程时做出正确的决策。一个进程可能会消耗过多的资源,影响在同一台机器上运行的其他进程的性能。
  • 自动扩缩容:以 PHP 应用程序为例,您必须管理每个服务器上的 PHP CGI 进程数量,并且必须对运行这些进程的服务器数量进行手动扩缩容。

FaaS 能很好解决上述两个难题,FaaS 明显有一些现代化的特点, 以函数计算执行环境容器的安全隔离为例[5]:



阿里云FC计算节点安全隔离

  • 虚拟化级别安全隔离

    • 神龙裸金属计算节点可运行来自不同用户的函数实例,使用阿里云安全沙箱提供函数级别虚拟化及容器隔离,ECS虚拟机只允许运行同用户的函数实例,借助ECS隔离提供用户级别虚拟化隔离,使用Runc等容器技术实现函数级别的容器隔离。
  • 函数实例网络访问受限,用户决定网络外访权限
    • 函数实例配置私有IP地址,用户不可直接访问,且实例间网络不可达,网络隔离使用 open vSwitch、iptables 和 routing tables 实现。
  • 函数实例资源受限函数CPU/内存设置的配额
  • 函数计算负责函数实例沙箱容器的漏洞修复及安全升级

使用 FaaS 这种事件驱动的全托管计算服务,您将自动获得隔离的执行环境实例,FaaS 服务自动管理执行环境实例的数量和容量。您所要做的事情就是提供您的代码到 FaaS 服务,并向 FaaS 服务发送事件以触发该代码执行即可。



FaaS 简略概览

从上面对 FaaS 并发扩缩容的讨论中,相信大家很快 get 到单个实例一个并发的能力对 CPU 密集型的逻辑非常友好。而现代的许多工作负载都充满了 I/O 操作,如果我们采用 FaaS 经典的 one concurrent request per instance 模式,会有如下痛点问题:

  1. 严重的资源浪费



IO-intensive workload[11]

蓝色方框表示程序正在工作时的时间,红色方框表示等待 IO 操作完成所花费的时间。由于 IO 请求可能比 CPU 指令花费的时间长几个数量级,因此您的程序可能会花费大部分时间等待, 实例资源浪费严重。并且随着并并发数目的变大,浪费的资源也呈线性增长,如下面红色部分即为浪费的计算资源:



FaaS IO-intensive workload

  1. 可能会对共享资源造成意想不到的后果

数据库是一个典型的例子。当使用传统的关系型数据库(如 mysql)时,数据库有一个最大并发连接数。传统常驻型服务器通常使用“数据库连接池”进行优化。“数据库连接池”限制了单个服务器实例对数据库的最大并发连接数,同时允许并发的请求能有效地共享“数据库连接池”的连接。然而,如果每个实例只能处理一个请求并维持与数据库的开放连接,则请求的数量与到数据库的连接数之间存在一对一的关系。结果是在负载高峰期间,数据库可能会因过多连接而打满,并最终拒绝新连接。如果一个数据库实例的最大连接数为 100,使用 FaaS, 示意图如下:



FaaS with DB

单实例多并发

因此,就 FaaS 领域的 one concurrent request per instance 的痛点问题, Google Cloud Run 提供了 multi concurrent requests per instance 的能力[6],这就很好解决我们上文讨论的单实例单并发扩缩容模型的痛点:

Google Cloud Run单个实例默认最大并发度(即单个实例的并发请求数上限)为80,最大可调整到1000

  1. IO等待期间不再是资源浪费



Google Cloud Run IO-Intensive workload

  1. 对共享资源造成影响可预期:提高数据库连接吞吐



Google Cloud Run With DB

如果每个实例配置了数据库连接池大小为 10,那么每个实例可以允许 10 个并行请求到数据库。由于每个实例可能会接收高达 80 个并发请求,“数据库连接池”将在等待数据库连接被释放并返回到池中时,自动阻止传入的请求。通过使用 10 个数据库连接响应 80 个请求,理论上可以在数据库达到其最大连接限制之前将数据库的吞吐量提高 10 倍。

有趣的是, 一些 FaaS 厂商勇敢做出了 multi concurrent requests per instance的尝试, 比如阿里云函数计算设置实例并发度 , Google Cloud Functions 第2代也开始支持设置实例并发度。旨在解决现代很重要的 IO 密集型工作负载问题。

为什么 Serverless 使用并发度进行扩缩容

FaaS 和 Google Cloud Run 采用实例并发度(即实例的并发请求数上限)这个指标进行扩缩容,而不是采用 CPU 指标等 HPA 策略,是因为在Serverless领域,实例并发度是“基于请求处理/事件驱动进行扩缩容”表达最好的一个方式。

  • FaaS 和 Google Cloud Run 都有实例缩至为 0 和有请求进来可以拉起一个新实例的能力,在实例 0-1 过程中无法使用 CPU 或内存等指标进行扩容。
  • 更好地匹配请求处理:并发度能够更好地匹配实际请求的数量,因此可以更好地利用计算资源,同时确保请求能够快速得到响应。以阿里云函数计算和 K8S 做一个资源匹配请求速度的对比[7]:

  • 更好的资源利用率:实例并发度策略可以更好地利用计算资源,可以在请求高峰期间快速扩容,而在请求较少时保持最小的实例数量,从而减少资源浪费。FaaS 和 Google Cloud Run 允许用户运行任何语言的代码,并自动扩展以匹配流量: 并发度总数 = 同时处理请求的实例数量 * 每个实例的最大并发请求数上限

当然,引入的并发度的概念也给习惯了 CPU 指标等扩缩容的开发者带来的新的疑惑, 对于 IO 密集型的应用,基于 CPU 指标的 HPA 扩容策略很简单就可以提高应用程序的可用性、性能和可靠性,并使资源更高效地利用。反而单个实例的最大并发度的合理值怎么去设置是一个比较头疼的问题? 这个问题,业界通常都是建议您根据自己的负载情况做压测迭代出合适的并发度值。 阿里云函数计算为此做了一个业界最前沿的探索, 提供了自动化推荐能力:从青铜到王者,揭秘 Serverless 自动化函数最佳配置[8], 并由此展望智能动态并发度:在这种模式下,用户不需要通过手动配置参数,而是在函数运行时动态调整,根据实例 CPU 负载的健康指标自动调整到最佳值。

结论

基于上文对并发度的讨论,对于单实例单并发(云产品代表 FaaS)和 单实例多并发(云产品代表 Google Cloud Run) 这两种形态的 Serverless 产品, 我应该选择哪个产品来托管我的应用程序呢? 以下是一些情景是我个人会选择哪种产品的建议:

但最终还是需要根据您具体的业务需求做取舍,选择最合适的产品和方案。

注:FaaS 中的函数计算 FC 和 Google Cloud Functions V2 也支持单实例多并发

场景 选择 理由
定期/事件触发的后台作业 FaaS 异步任务,不关心冷启动时的延迟, 典型的事件驱动
非预期的时间流量波峰和波谷切换 FaaS 函数实例将扩容以处理流量激增,并在波峰结束时进行缩减。与burst流量所带来的高延迟相比,冷启动可能会对性能产生较小的影响。
每个请求必须相互隔离或者 CPU 密集型任务,例如:
  • Puppeteer 对 HTML 页面截图
  • Word 转 PDF 等文档转换
  • 前端领域 SSR 渲染
  • 音视频转码、录屏等处理
  • 机器学习 AI 推理, AIGC
  • ...

    | 单实例单并发 FaaS | 每个请求隔离特性非常适合将这些潜在的恶意作业彼此隔离开来, 同时每个实例保证了确定的 CPU 和内存的配额。
  • 某个请求执行时间超过函数设置的 timeout 自动被 kill
  • 某个请求导致实例的 OOM 不会扩散, 只会影响这个一次请求
  • ...

    |

    | 可预期流量的 IO 密集型应用 | 单实例多并发云产品 | 避免资源浪费,更好保护下游比如 mysql 数据库 |

    | 非 HTTP 协议应用 | 单实例多并发云产品 | FaaS 厂商大多不支持, 或者像阿里云 FC 支持WebScoket 这种非 HTTP 协议, 但是成本不占优势 |

上述表格中的建议是基于阿里云函数计算应用中心[9]中的用户对于应用的偏好部署次数【见下图】以及客户落地案例【见参考12】来佐证的, 尤其对于每个请求必须相互隔离或者 CPU 密集型任务, FaaS 具有无与伦比的优势:

  • 对于存量应用,将 CPU 密集型任务从应用中抽离出来,提升服务的稳定性,这个文章 PDF Generation With AWS Lambda[10] 深入讨论了这种实践的收益。
  • 对于新业务 CPU/GPU 密集型应用, 如音视频处理以及最近大火的大模型 AIGC(AI generated content ) 应用, 是 FaaS 天然契合的场景 。

在 AI 场景中请求和后端资源的调度比传统的微服务场景的要求会更高,主要原因是 AI 场景的请求对资源的消耗特别大。比如一个 Stable Diffusion 使用 A10 GPU 卡部署,一块 A10 卡(ecs.gn7i-c8g1.2xlarge) 启动 Stable Diffusion 服务一次只能处理个位数的文本绘图请求。一旦同时进来请求过多,就会出现计算资源竞争从而导致请求超时的情况。而 FaaS 的 "one concurrent request per instance" 天然契合这个场景, 简直就是绝配。



函数计算FC应用中心文件处理应用部署情况图



函数计算 FC 应用中心音视频处理应用部署情况图



函数计算FC应用中心AI应用部署情况图

参考

  1. https://www2.eecs.berkeley.edu/Pubs/TechRpts/2019/EECS-2019-3.pdf
  2. https://glossary.cncf.io/serverless/
  3. https://docs.aws.amazon.com/lambda/latest/operatorguide/scaling-concurrency.html
  4. https://nathanpeck.com/concurrency-compared-lambda-fargate-app-runner/files/Concurrency%20Compared.pptx
  5. https://help.aliyun.com/document_detail/438853.html
  6. https://cloud.google.com/run/docs/about-concurrency?hl=zh-cn
  7. https://developer.aliyun.com/article/1243681
  8. https://developer.aliyun.com/article/1161868
  9. https://help.aliyun.com/document_detail/606948.html
  10. https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77
  11. https://realpython.com/python-concurrency/
  12. 基于函数计算应用中心落地案例参考
  13. 网易云音乐音视频算法的 Serverless 探索之路
  14. 聚焦弹性问题,杭州铭师堂的 Serverless 之路
  15. 优化 20% 资源成本,新东方的 Serverless 实践之路
  16. 当 Rokid 遇上函数计算
  17. 多家游戏公司 apk 实时打渠道包 repackAPK
  18. ...

免费报名 Serverless 技术实战营

报名地址:

https://www.huodongxing.com/event/9709144075400?td=3304156735350

深入理解 Serverless 计算的并发度的更多相关文章

  1. 用实例的方式去理解storm的并发度

    什么是storm的并发度 一个topology(拓扑)在storm集群上最总是以executor和task的形式运行在suppervisor管理的worker节点上.而worker进程都是运行在jvm ...

  2. [Storm] 并发度的理解

    Tasks & executors relation Q1. However I'm a bit confused by the concept of "task". Is ...

  3. storm源码之理解Storm中Worker、Executor、Task关系 + 并发度详解

    本文导读: 1 Worker.Executor.task详解 2 配置拓扑的并发度 3 拓扑示例 4 动态配置拓扑并发度 Worker.Executor.Task详解: Storm在集群上运行一个To ...

  4. 关于Storm 中Topology的并发度的理解

    来自:https://storm.apache.org/documentation/Understanding-the-parallelism-of-a-Storm-topology.html htt ...

  5. storm并发度理解

    1. 核心原理 一个运行中的拓扑是由什么组成的:worker进程,executors和tasks.Storm是按照下面3种主要的部分来区分Storm集群中一个实际运行的拓扑的:Worker进程.Exe ...

  6. 【转】理解Serverless

    理解Serverless No silver bullet. - The Mythical Man-Month 许多年前,我们开发的软件还是C/S(客户端/服务器)和MVC(模型-试图-控制器)的形式 ...

  7. 理解serverless无服务

    理解serverless无服务 阅读目录 一:什么是serverless无服务? 二:与传统模式架构区别? 三:serverless优缺点? 四:使用serverless的应用场景有哪些? 回到顶部 ...

  8. 利用Azure Functions和k8s构建Serverless计算平台

    题记:昨晚在一个技术社区直播分享了"利用Azure Functions和k8s构建Serverless计算平台"这一话题.整个分享分为4个部分:Serverless概念的介绍.Az ...

  9. storm基础系列之一----storm并发度概念剖析

    前言: 学了几天storm的基础,发现如果有hadoop基础,再理解起概念来,容易的多.不过,涉及到一些独有的东西,如调度,如并发度,还是很麻烦.那么,从这一篇开始,力争清晰的梳理这些知识. 在正式学 ...

  10. Storm基本概念以及Topology的并发度

    Spouts,流的源头 Spout是Storm里面特有的名词,Stream的源头,通常是从外部数据源读取tuples,并emit到topology Spout可以同时emit多个tupic strea ...

随机推荐

  1. windows下tomcat开机自启动

    在Windows下,可以通过以下步骤将Tomcat设置为开机自启动: 1. 打开Tomcat安装目录:通常情况下,Tomcat的安装目录位于`C:\Program Files\Apache Softw ...

  2. VUE2.0 学习 第一组

    本笔记主要参考菜鸟教程和官方文档编写. 1. 对于Vue2.0来说每个vue应用都需要实例化vue来实现. var vm = new Vue({ // 选项 }) 2.首先,DOM是一种api,它可以 ...

  3. Head First Java学习:第九章-构造器和垃圾收集器

    对象的前世今生 对象如何创建.存在何处以及如何让保存和抛弃更有效率. 会述及堆.栈.范围.构造器.超级构造器.空引用等. 1.内存的两个区域:堆和栈 堆(heap):对象的生存空间,又称为可垃圾回收的 ...

  4. SpringMVC中资源路径映射本地文件图片

    SpringMVC中资源路径映射本地文件图片 import org.springframework.context.annotation.Configuration; import org.sprin ...

  5. 【笔记】01 -- Spring-Cloud介绍

    第一章节我们主要是介绍微服务 springCloud的架构和分布式的区别 但是后面会主要介绍netflix公司与Alibaba公司的两套架构 系统架构 **概述** 随着互联网的发展,网站应用的规模不 ...

  6. 神经网络优化篇:详解神经网络的权重初始化(Weight Initialization for Deep NetworksVanishing / Exploding gradients)

    神经网络的权重初始化 这是一个神经单元初始化地例子,然后再演变到整个深度网络. 来看看只有一个神经元的情况,然后才是深度网络. 单个神经元可能有4个输入特征,从\(x_{1}\)到\(x_{4}\), ...

  7. 永久免费!国产操作系统 Deepin V20 Beta版发布(附安装教程)

    深度操作系统(DEEPIN)是武汉深之度科技有限公司致力于为全球用户提供美观易用.安全可靠的Linux发行版.经过一段时间的测试,这款操作系统的Beta版终于今天和大家见面了.这次Deepin v20 ...

  8. fence的使用

    一.创建一个集群及pcs安装 1.真机切换root用户下 2.打开PC管理器视图 1.安装pcs,关掉防火墙,重启pcs和下次开机自动启动pcs 1.创建一个集群,用户:hacluster:密码:re ...

  9. P6357 题解

    Luogu 题面 题目描述 给定一串长度为 \(n\) 的数字,数字为 \(0 \sim 9\) 之间的任意一个,下标从 \(1\) 记起. 然后进行 \(m\) 次区间查询,每次查找区间 \([l, ...

  10. Java 查找并高亮PDF中的跨行文本

    以下内容介绍如何在Java后端程序中查找并高亮PDF文档中的跨行文本.本次测试环境如下: 源文档:PDF 编译工具:IntelliJ IDEA2018 JDK:1.8.0 PDF类库:free spi ...