开发者学堂课程【Serverless 函数计算架构:阿里云 FaaS 架构设计】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/843/detail/14013
阿里云 FaaS 架构设计
内容简介:
一.基于 ECS 的 FaaS
1.ECS/Container+负载均衡
2.基于 ECS 的 FaaS 架构设计
3.多租户多应用部署的支持
4.快速水平弹性扩容
5.如何提升资源利用率
6.如何容灭、防止雪崩
二.基于神龙高密部署的 FaaS
1.为什么需要做高密部署
2.高密部署架构带来的技术难题
3.基于安全容器模板技术的优化
4.代码按需加载
5.基于网络服务网格的 VPC 网络代理
6.资源分配率
7.总结
8.未来的方向和技术挑战
一.基于 ECS 的 FaaS
1.ECS/Container+负载均衡
用户的请求通过互联网进来之后,会先进到负载均衡里面,然后通过负载均衡均匀的把系统的请求调度到不同的 ECS 机器上。这里的三台 ECS 机器都是对等的机器,每一台机器里面部署的应用都是一模一样的,那么当用户请求进来之后,会直接分散到每台机器上去(比如 A 请求可能到第一台机器上,B 请求可能到第二台机器上,C 请求可能到第三台机器上)。HTTP 请求里面有个 keep lab 设置,这个时间通常会控制在一个很短的时间(可能分钟级别),如果不去控制设置,可能大量请求都会堆到一台机器上。把时间设置好之后,请求就会慢慢的打散到不同的机器上,然后每一台机器通过业务计算之后再把数据给写到数据库里面去,但是会带来以下问题:
1)多应用配比部署资源
比如,A 业务的峰值比较高,那么它的业务访问会非常频繁,B 业务是比较低频的业务,如果把它们混在一台机器上,假如A业务需要的请求上涨,而 B 业务的请求还是一样多的话,那么配比情况是在变化的。如果只是打在一台机身一个镜像上面,再去做一些调整的话,这个时候比例已经失衡了,就会带来资源的浪费。
2)镜像升级替换繁琐
假如某一个业务出现了异常,要把它给改掉,那么所有的机器都要去换一遍。
3)弹性扩缩容速度较慢
如果把一个镜像换掉,需要先把镜像升级出来,然后再实时启动一台新的机器把给镜像恢复出来。在机器启动过程中,开机速度是在分钟级别,但是扩容的速度相对就比较慢。
2.基于 ECS 的 FaaS 架构设计
1)SLB 负载均衡
抵挡 DDoS 攻击
请求均衡到多台 api_server
2)api_server
发起函数的 CRUD 操作
向 scheduler 申请容器
向 worker 中的容器发起请求执行
3)Scheduler
管理容器在 worker 的放置
请求落在容器上的调度分发
4)Worker
用户所在的计算节点
5)ENI
打通到用户 VPC 环境的网卡
请求通过互联网进来,落到负载均衡的节点上,这块也是整个函数计算的一部分,是部署在阿里云内部的。IPSO 是对等的,它上面是不保存用户状态的,主要是用来做用户的请求分发,包括用户请求的一些数据校验。IPSO 可能会连一些数据库,比如 OTS 表格存储,然后把用户的一些数据给拉到内存当中做一些校验。
请求进来之后会问 scheduler 要资源。首先需要有一台机器,然后把用户的应用在这台机器上启动起来,那么得到对应机器的上面就是 worker。Work_pool 相当于机器池,机器池里面的每一台机器都是提前启动好的,但是上面没有部署任何用户代码,等到机器池中的机器被取到 scheduler 之后,scheduler 会根据用户的请求把相关的代码通知给 worker 内部的 agent。下载好之后再启动一个进程,启动的过程当中相当于把用户的代码给挂载到它所在的容器里面,容器里面对应的就是用户的进程。
用户所在的 worker 称之为计算节点。这个计算节点上面需要绑定一个网卡,但也不是必须的。如果需要访问VPC(虚拟私有网络)内部的数据,通常是用 ENI 网卡来挂载到这台机器上,那么这个网卡只允许给这一个用户使用。
3.多租户多应用部署的支持
CGroup/Namespace 资源隔离,可以在操作系统层面做一些设置,可以指定让一部分进程固定使用多少的 CPU,多少内存,指定用哪一个网卡,哪一个方面的 IP。即一个应用就是有一个虚拟的资源隔离的方案。
Container,相对包装的更加完善。大部分情况下,用户看到的是一个相对来说比较完整的操作系统。只要用户把相关的数据放置在这个容器当中,那它的数据就没办法直接逃离出去。
当把单个用户放置在一个虚拟机当中,一个VM就相当于一台 ECS,操作系统层面就是把整个 CPU、memory 包括设备全部给屏蔽掉。操作系统和 CGroup 来控制整个CPU 内存、文件系统的划分,用户看到的是 container 内部,它的应用部署在容器里面。
用户独占虚拟机,因为所有的用户都是共用的一个操作系统的内核。同时有一部分内存是共享的,高级开发者有机会去破解,或者从 container 中逃逸出来,这样就对另外一个用户有产生危险的可能。如果把两个不同的用户混在一台 ECS 上面,对于用户之间是有风险的。为了屏蔽这种风险,一台 ECS 只对应于一个用户。
4.快速水平弹性扩容
1)应用容器部署
因为应用完全都是部署在容器当中,所以可以定制一些特别的语言 Runtime 容器,包括一些通用的 LIB 库、SDK。比如表格存储,它的 SDK 就可以写到镜像当中,用户就不需要额外的去下载了,只要保持跟社区生态一致即可。
2)机器资源池
所有的容器镜像都写到了 ECS 的镜像当中,即整个 ECS 一启动,所有的容器镜像就存在本地磁盘了,那么机器启动之后就可以直接拿来用,只需要把用户的代码部署上去即可。如果机器池当中缺少机器,可以直接添加新的机器,只要控制机器池的大小,就能够兼顾性能跟成本。
3)容器池化启动
当 ECS 虚拟机启动之后,立马把容器也创建出来,但是不立即把用户的代码给加进来去。因为在池化之前,这个机器在资源池中的时候,还不知道这台机器将来会给哪一个用户使用。等到用户真正的请求来临之后,再把用户的代码给延迟挂载进去,然后再做用户的调用。因为容器启动也是需要时间的,这个时间可能是在数百毫秒到几秒之间,如果把这个东西全部池化掉,那么 health check、资源申请等都可以提前做。做完之后,当用户的请求来临时,需要的启动时间会变得更短。
4)控制应用大小
应用的大小通常是和用户代码库相关的,比如用了 Java,可能引入了一堆的package,那么会鼓励用户把这个业务给拆分出来,让整个应用更小。应用更小意味着它下载代码包需要的量就相对会更少,同时也会意意味着启动速度会更快。
5)P2P 镜像下载加速
容器镜像需要涉及到 P2P 镜像分发。通常容器镜像可能会在数 10 兆到数 G 之间,大量的下载服务很难提供更高的带宽,而 P2P 的镜像分发可以避免对下载服务造成太大的空间冲击,同时也可以降低下载延迟,提升启动的速度。
5.如何提升资源利用率
相同 QPS 下单位时间片内调度对资源量的影响。
总共有 6000 多个容器,实际上只有 2000 多个容器正在被用户调用,剩下的 4000多个容器是在空闲的状态。由于用户的 QPS 是不断的打进来的,但是这个调度还是有很多空闲的容器,相当于 4000 多个容器完全被浪费掉了。
把时间片缩得非常短,上面是在宏观状态下,下面是在微观状态下,会发现 5 毫秒以内它的最大连接数是 300 多,实际上平均连接数只有 137。造成这种现象的原因如下:
1)均匀调度下的资源
任意时刻只需要一个容器
2)调度滞后下的资源
某些时刻需要数倍容器
3)调用耗时及冷启动延迟
加剧容器量的开销
通过调度提升资源使用率,可以让请求更加离散,把请求全部集中在某一个点的话,就会造成资源的浪费。在第二种情况当中,如果这 6 个请求完全集中在一个点,那么相当于需要 6 个容器。如果把这个时间分摊到第一种情况下,只需要一个容器就可以了。
总结:(1)尽可能把请求离散到不同的时间片上去;(2)缩短能启动的时间,这样就可以提升整个资源的使用率。
6.如何容灭、防止雪崩
实际当中,当异常发生的时候,用户的请求通常会执行出错,那么我们会把用户的进程重启,或者把请求调到新的资源上。新的资源可能会涉及到新的资源申请、创建新的软件,这样会导致整个的延迟增大。当用户发现服务端响应速度过慢的时候,他会疯狂的去点击浏览器的刷新按钮,这样就会造成大量的请求重新发到服务器端,服务器的压力会越来越大,会造成异常发生,更加恶化。
优化方法如下:
1)优化启动速度
优化启动速度相当于重启或者调用调度新资源,它的速度会更快。如果速度更快,用户收到的响应会更及时,那么重试这个动作可能会减缓。
2)多 Partition 容灾部署
多 Partition 部署和重新调动资源有一些关系,就是把它调不到不同的机器上去。
3)指数退避重试
在前端的 APP 上面可以做一些控制,把多余的请求直接忽略掉,做成自动重试,这就是指数退避重试,它的效果会比常数的退避好很多。
4)Breaker 阻断异常请求
比如发现异常了,第一个请求异常,会继续服务,第二个请求异常,会记录这个异常请求的时间间隔,如果发现在某一个时间点集中异常出现,那么会直接把整个服务暂时断掉。等到后端的服务恢复了,或者下一个计时点发现它的密集度变稀疏了,然后再次重新恢复。
5)多可用区备灾
多可用区备灾涉及到阿里云机房的部署,在 ECS 机器的那一层面上做了设置。后端机器是在多个可用区的,如果一个出现异常了,那么切到其他可用区即可。
6)SLB 阻断 DDoS 攻击
二.基于神龙高密部署的 FaaS
1.为什么需要做高密部署
1)弹性
在函数计算这个场景业务场景下,对弹性启动的速度有要求,希望做到每秒1万个容器实例的启动。单个容器的启动延迟控制在 300 毫秒以内。容器的存活时间通常是在分钟级别,但是 ECS 的级别是天级别,一般的 ACK 容器服务。对弹性的要求相对来说是更高的。
2)成本
一个 ECS 只能提供给一个用户使用,资源使非常浪费的。要想使利用率更高,使用成本更低,就要做一些高密的部署,把用户集中部署到少部分机器上面的,这样单台机器的使用率会变高。
3)性能
ECS单机缓存相对较少。比如一个 8G 的 ECS,上面部署了两个 4G 的容器,那么它需要下载一份代码。但是在不同的机器上,比如在 A 机器需要下一次,在 B 机器上又要下一次,总共需要下两次。如果机器数越多,下载的次数也就多,那么每个新请求,它平均遇到的人启动次数也就越多,它的延迟也就会越高。
4)稳定性
ECS 数量越多,涉及到资源的删除频率也就会更高,启动频率也会更高,这样对于ECS 整个系统的管控压力也就会越大。如果出现异常了,就会影响很多用户。
2.高密部署架构带来的技术难题
1)如何解决单机多租户隔离安全风险?
2)如何解决高并发下启动速度问题?
3)如何解决单机多租户 VPC 网络打通及安全隔离问题?
4)如何设计高密部署下的技术容灾方案?
3.基于安全容器模板技术的优化
申请一个神龙物理机,API_Server 和 scheduler 没有太大变化。但是在这台物理机上面做了不同的事情。首先,用户请求打进来会掉到 Agent 上面,那么 Agent 就会去创建一个杀伤环境下的安全软件。杀伤相当于是一个独立的虚拟机,它有自己独立的微内核(Linux 内核),已经把这个内核的实现做了很多优化,去掉了很多不必要的东西,让其所有的内存占用控制在 20兆 以内。那么整个这台机器上可以容纳的微内核的数量也就更多了。
架构上做一个网络的隔离。相当于把用户在微内核上所有的程序的流出,通过网卡导出到 forwarder 上面,再通过本地机器上的 ENI 网卡导出到 ANSM,即阿里云的一个网络服务网格。通过网络服务网格出去,然后导出到用户 VPC 上面。Nydus 负责整个用户的代码的加载。整个机器上还有很多用户就这样通过安全容器的微内核来做隔离,可以做到单台机器上,每个微内核大概 20兆。所谓的内层,同时有2000 多个容器部署在上面,控制它的冷启动时间是在 250 毫秒左右。
4.代码按需加载
这里用的是 nydus 的方案,nydus 是部署在安全容器上面的,但是下面这一部分的存储可以是 NAS 或者 OSS。用户在加载代码的时候有可能因为代码本身很大,脚本里面很多的实现可能只要引用到几个文件,那么大部分的数据它只要做到,用了一个file的技术,就是通过用户空间文件系统的读取。
如果要做整个数据的下载,就可以放在 OSS 上面,因为 OSS 的数据是异步去读取的,其速度会延迟加载。前面会利用 NAS 去读取,导致整个代码下载速度会变得非常快。
5.基于网络服务网格的 VPC 网络代理
这里有蓝色的是表示一个用户,黄色表示另外一个用户。这两个用户的请求部署在同一个计算节点上面,通过 forwarder 出去,中间一层是网关集群,即 VPC 网关代理。在网关代理上面,插上网卡,对应的就是 VPC A 和 VPC B,这样去做网卡的缓存就不会立马 GC 掉。插拔 ENI 网卡本身非常耗时,需要 2~3 秒钟,但是只要提前部署好,其他的计算节点在启动的过程当中就不需要另外在系统里启动,那么整个网卡的加载速度会变得很快。
6.提升资源的分配率
4台 ECS 上面有多个容器,如果有大量的容器,离散部署会产生很多的内层空洞。如果把它集中部署到一个大的机器上面,内存空洞就会减少,整台机器的碎片会更少。
7.总结
整个神龙通过神龙裸金属加安全容器,可以实现到更高一层的调动,即下一代架构,可以做到单用户 3000 并发,计算密度 50 以上的实例,把延迟控制在 300 毫秒以内,CPU 的使用率也做到了很大提升。
8.未来的方向和技术挑战
1)资源使用率
容器的放置,可以把调度做到更好;
容器创建,在哪台机器上创建,控制比较好就可以节省资源;
Scating,平滑调度,可以把它离散到不同的时间片里面去,资源使用率会更低。
2)启动速度
如果把延时降低,它的启动速度也会更快;
在单机并发速度上面做一些优化,可以让单击启动的速度更快。
3)高可用
怎么做到单机容灾的效果。