APP下载

一种高性能Serverless计算设计

2022-02-03陈富强

现代计算机 2022年21期
关键词:开发者代码容器

陈富强

(广州华商学院数据科学学院,广州 510000)

0 引言

在传统开发模式中,开发一个应用程序,从开始到上线需要不同的角色来做不同的事情,沟通成本非常大,并且运维过程中需要考虑到服务器的负载均衡、事务、集群、缓存、消息传递和数据冗余等事情。

云计算涌现出很多改变传统IT 架构和运维方式的新技术,比如虚拟机、容器、微服务,无论这些技术应用在哪些场景,降低成本、提升效率是云服务永恒的主题。Serverless 架构就是在云计算背景下产生的,基于Serverless 架构后端的应用被拆分成为一个个函数,只需要编写完成函数后部署到Serverless 服务即可,不用关心任何服务器的操作,大大提高了开发的效率,减少了沟通的成本。

Serverless 中文的含义是"无服务器",但是它真正的含义是开发者再也不用过多考虑服务器的问题,但是并不代表完全去除服务器,而是依靠第三方资源服务器后端,比如使用Ama⁃zon Web Services(AWS)Lambda 计算服务来执行代码。Serverless 架构分为Backend as a Service(BaaS)和Functions as a Service(FaaS)[1]两种技术,Baas 的含义是后端即服务,它的应用架构由大量第三方云服务器和API 组成,使用中关于服务器的逻辑和状态都由服务提供方来管理。比如典型的单页应用SPA 和移动APP 客户端应用,前后端交互主要是以RestAPI 调用为主。只需要调用服务提供方的API 即可完成相应的功能,比如常见的身份验证,云端数据/文件存储,消息推送,应用数据分析等。

FaaS 可以被叫做:函数即服务。开发者可以直接将服务业务逻辑代码部署、运行在第三方提供的无状态计算容器中,开发者只需要编写业务代码即可,无需关注服务器,并且代码的执行是由事件触发的。其中AWS Lambda是目前最佳的FaaS 实现之一。Serverless 是由开发者实现的服务端逻辑运行在无状态的计算容器中,它是由事件触发,完全被第三方管理。

Serverless 计算是一种无需管理服务器即可构建和部署云服务的方法[2]。与IaaS(基础设施即服务)相比,Serverless 计算提供了更高级别的抽象,因此有望提供更高的开发人员生产力和更低的运营成本。无服务器计算的关键特征包括资源弹性零操作和即用即付。

最初的云服务AWS S3(Simple Storage Ser⁃vice)[3]是无服务器的,但仅用于存储,实践证明很难扩展代码执行。IaaS 成为主导的云服务,开发人员提供虚拟机(服务器)来部署应用程序。开发者负责规划、配置、部署和维护服务器,即使是更高级的PaaS(平台即服务),开发者也只是获得了预装软件堆栈的虚拟服务器,必须根据分配的资源付费(例如CPU 和内存),而不是实际使用情况付费。

近年来,由AWS lambda 首创的新一代云服务使开发人员能够直接基于代码功能创建Web服务。开发人员无需配置或管理服务器,云提供商在请求到来时自动部署执行环境,并根据运行的需求扩展执行环境,这种方法被称为功能即服务(FaaS)。行业报告表明,FaaS 已经受到云计算用户的欢迎,并可能成为未来云计算的主导形式。

FaaS 的兴起得益于虚拟化和容器化技术的进步,这可以让开发者以最小的开销频繁启动和停止执行环境。领先的公共云提供商使用系统虚拟机和应用程序容器的组合作为FaaS 的基础设施。与系统虚拟机相比,Docker 等应用容器更快更轻[2],但安全性相较于虚拟机要低。

在当前主流的FaaS 应用中,AWS Lambda是基于一种名为Firecracker 的轻量级虚拟化技术。Firecracker也称为micro VM,比传统系统虚拟机更轻、更快,因此适用于Faas 工作负载;IBM Cloud 功能利用Docker 容器提供隔离;微软Azure[4]功能兼容Docker,但部署在公有云时增加了虚拟机保护;谷歌云功能采用了一种折衷的方法,其g Visor 引擎主要目的是在公共云中安全运行Docker。然而,g Visor 引擎比普通Docker慢2倍。

即使有那些性能优化的系统虚拟机和应用程序容器,FaaS仍然存在性能和扩展性问题:

一是冷启动慢。配置和启动micro VM 或容器可能需要几秒钟,其中每个函数执行都可能需要一个新的micro VM 或容器,此问题还会导致不一致的问题和可能出现一些不可预测的运行结果,因为函数的执行可能还要比运行环境的启动更快一些。

其次,虚拟机或容器必须为每个函数调用设置一个运行时软件堆栈,包括不同操作系统的标准库。这是一种很大的资源消耗。

最后,虚拟机或容器只能测量粗粒度的资源消耗,例如使用的分配内存和执行时间。而它们不支持基于准确CPU 执行周期的细粒度使用计费。

在本文中,将讨论一种不依赖于虚拟机和容器的FaaS方法。

1 Serverless

Serverless 中文的含义是"无服务器",但是它真正的含义是开发者再也不用过多考虑服务器的问题[1],但是并不代表完全去除服务器,而是依靠第三方资源服务器后端。

在现阶段,Serverless 主要应用在以下几个场景:在Web 及移动端服务中,可以整合API网关和Serverles 服务构建Web 及移动后端,帮助开发者构建可弹性扩展、高可用的移动或Web 后端应用服务;在IoT 场景下可高效地处理实时流数据,由设备产生海量的实时信息流数据,通过Serverles 服务分类处理并写入后端处理。另外在实时媒体资讯内容处理场景里,用户上传的音视频到对象存储OBS,通过上传事件触发多个函数,分别完成高清转码、音频转码等功能,满足用户对实时性和并发能力的高要求。无服务器计算还适合于任何事件驱动的各种不同的用例,这包括物联网、移动应用,基于网络的应用程序和聊天机器人等。

场景一:应用负载有显著的波峰波谷

Serverless 应用成功与否的评判标准并不是公司规模的大小,而是其业务背后的具体技术问题,比如业务波峰波谷明显,如何实现削峰填谷。一个公司的业务负载具有波峰波谷时,机器资源要按照峰值需求预估;而在波谷时期机器利用率则明显下降,这是因为不能进行资源复用而导致的浪费。

业界普遍共识是,当自有机器的利用率小于30%,使用Serverless后会有显著的效率提升。对于云服务厂商,在具备了足够多的用户之后,各种波峰波谷叠加后平稳化,聚合之后资源复用性更高。比如,外卖企业负载高峰是在用餐时期,安防行业的负载高峰则是夜间,这是受各个企业业务定位所限的;而对于一个成熟的云服务厂商,如果其平台足够大,用户足够多,是不应该有明显的波峰波谷现象的。

场景二:典型用例-基于事件的数据处理

视频处理的后端系统,常见功能需求如下:视频转码、抽取数据、人脸识别等,这些均为通用计算任务,可由函数计算执行。

开发者需要自己写出实现逻辑,再将任务按照控制流连接起来,每个任务的具体执行由云厂商来负责。如此,开发变得更便捷,并且构建的系统天然高可用、实时弹性伸缩,用户不需要关心机器层面问题。

对于企业来说,支持Serverless 计算的平台可以节省大量时间和成本,同时可以减轻员工负担,让开发者得以开展更有价值的工作。另一方面可以提高敏捷度,更快速地推出新应用和新服务,进而提高客户满意度。

但是Serverless 对应用来说不是完美的,存在以下问题:

(1)不适合长时间运行应用

Serverless 只有在请求到来时才运行。当应用不运行时就会进入“休眠状态”,下次当请求来临时,应用将会需要一个启动时间,即冷启动时间。如果应用需要一直长期不间断的运行、处理大量的请求,那么可能就不适合采用Serverless 架构。如果通过CRON 的方式或者CloudWatch 来定期唤醒应用,又会比较消耗资源。这就需要对Serverless 架构做优化,如果频繁调用,这个资源将会常驻内存,第一次冷启动之后,就可以一直服务,直到一段时间内没有新的调用请求进来,才会转入“休眠”状态,甚至被回收,从而不消耗任何资源。

(2)完全依赖于第三方服务

当企业云环境已经有大量的基础设施时,Serverless 对于应用来说并不是一个好的解决方案。当采用某云服务厂商的Serverless 架构时,应用就和该服务供应商绑定了,那么再将服务迁到别的云服务商上就没有那么容易。因此项目需要修改一下系列的底层代码,而能采取的应对方案,便是建立隔离层。建立隔离层意味着在设计应用的时候,就需要隔离API 网关、隔离数据库层,市面上还没有成熟的ORM 工具,既支持Firebase,又支持DynamoDB 等,这些也将带来一些额外的成本,可能带来的问题会比解决的问题多。

(3)缺乏调试和开发工具

每次当项目需要调试时,需要一遍又一遍地上传代码。每次上传的时候,像是在部署服务器,并不能总是快速地定位出问题在哪。针对这个问题,项目可以使用一个类似于log4j 的可以分级别记录日志的Node.js 库winston。可支持error、warn、info、verbose、debug、silly 六个不同级别的日志,再结合大数据进行日志分析过滤,快速定位问题。

(4)构建复杂

Serverless 很便宜,但构建起来并不简单。AWS Lambda 的Cloud Formation 配置非常复杂且难以实现及编写(JSON 格式),虽然Cloud For⁃mation提供了Template模板,但想要在项目中使用的话,需要创建一个规定的Stack,在Stack中指定要使用的模板Template,然后AWS 才会按照Template中的定义来创建及初始化资源。

而Serverless Framework 的配置相对简单,采用的是YAML 格式。在部署的时候,Server⁃less Framework 会根据配置生成Cloud Formation配置。然而这也并非是一个真正用于生产的配置,真实的应用场景远远比这复杂。

2 WebAssembly简介

WebAssembly(缩写为wasm)是一种使用非JavaScript代码,并使其在浏览器中运行的方法。这些代码可以是C、C++或Rust 等。它们会被编译进浏览器,在CPU 上以接近原生的速度运行。这些代码的形式是二进制文件,可以直接在JavaScript 中将它们当作模块来用。WebAs⁃sembly 不能替代Javascript,相反,这两种技术是相辅相成的。通过JavaScriptAPI,可以将WebAssembly 模块加载到页面中。也就是说,可以通过WebAssembly 来充分利用编译代码的性能,同时保持JavaScript 的灵活性。WebAs⁃sembly 的使用场景远不止于适用于Web 浏览器,还适用于各种需要提升运行性能的场景。此外,WebAssembly 不是编程语言,而是一种中间格式,叫字节码,可以作为其他语言的编译目标。

WebAssembly 是一种新的字节码格式,主流浏览器都已经支持WebAssembly。和JS 需要解释执行不同的是,WebAssembly 字节码和底层机器码很相似,可快速装载运行,因此性能相对于JS 解释执行大大提升。换言之,WebAs⁃sembly 并不是一门编程语言,而是一份字节码标准,需要用高级编程语言编译出字节码放到WebAssembly虚拟机中才能运行。

尽管WebAssembly 是为运行在Web 上设计的,但它也可以在其它的环境中良好地运行。包括从用作测试的最小化shell,到完整的应用环境——例如:在数据中心的服务器、物联网(IoT)设备或者是移动桌面应用程序。甚至,运行嵌入在较大程序里也是可行的。

非Web 环境下,它有和Web 环境下不同的应用编程接口(API)。功能测试(feature testing)和动态链接(dynamic linking)会使其可自发现、易于使用。非Web 环境可能包括JavaScript 虚拟机(例如node.js)。但是,WebAssembly也被设计为能够在没有JavaScript虚拟机的情况下运行。

WebAssembly 标准本身不会尝试定义任何大型可移植的类库。然而,作为WebAssembly语义核心库中的函数的某些功能,将以原始操作符(primitive operators)的身份,成为核心WebAs⁃sembly 标准的一部分。对于在Web 和流行的非Web 环境之间存在重叠的地方,将会有共享的规范。

为了保证多数情况下可运行性,源码级别的可移植性。开源社区将会构建从源码级别的接口,映射到主机环境内置功能的库(在运行时或构建时)。WebAssembly 会提供原始构建块:包括功能测试(featuretesting)、内建模块(built⁃ingmodules)以及动态加载(dynamicloading)。早期已经应用WebAssembly 构建功能库的例子是POSIX 和SDL。因为WebAssembly 支持C/C++级语义,不需要WebAPI 的非Web 路径,WebAs⁃sembly 能够在许多平台上用作便携式的二进制格式,为移植性、工具和语言无关性提供了很强的便利性。

3 基于WebAssembly的设计方法

Serverless FaaS 必须为用户提交和不受信任的代码提供安全和隔离的执行环境。本文提出基于Webassembly 设计是FaaS 的一种更轻、更快的替代方案。与系统虚拟机和Docker 容器不同,WebAssembly 是一种字节码格式,可以将高级语言编译成机器语言。

WebAssembly 最初是为了提高Web 浏览器内的JavaScript 性能。由于它原本设计成执行从Web 下载的代码,出于安全考虑,WebAssembly运行的过程中为不受信任的代码提供了基于软件的故障隔离(SFI)沙箱。

WebAssembly 支持多种编程语言,例如C/C++和Rust。WebAssembly 系统接口标准允许WebAssembly 运行时与操作系统资源接口,这使其适用于服务器端应用程序。WebAssembly可以安全地运行,并且可以在不同的底层平台上按需启动和停止这些功能,而无需更改任何代码。由于WebAssembly 在操作码级别提供抽象,因此它可以在运行时精确测量细粒度的资源消耗。

WebAssembly 相对于系统虚拟机、micro VM和Docker 容器的最重要优势是性能较好和占用空间较小。一些云提供商,例如Fastly 和Cloud⁃flare,已经在其边缘网络上提供基于WebAssem⁃bly的FaaS服务。在本研究中,以Docker容器为基准评估WebAssembly 运行时的性能,之所以选择Docker 作为基准比较,是因为Docker 代表了非WebAssembly的FaaS服务的最佳性能。

WebAssembly 在FaaS 中相对 于Docker 的性能优势已在文献[5]中有所记载。本文研究有几个明显的差异,即本研究不是对集成用例进行计时,而是评估标准性能基准,例如多线程效率或磁盘I/O。此外,还使用不同的优化策略评估了WebAssembly运行性能。

4 结果比较

本文在两个大型云平台阿里云ECS 和腾讯云CVM 上进行了实验。两台主机上都运行Ubuntu linux 20.04tls。硬件配置如下:

ECS:Intel cpu 2.30GHz with 8 cores and 32 GB of RAM;

CVM:Intel cpu 2.50GHz with 4 cores and 16 GB of RAM。

评估以下运行环境:

最新的稳定版docker 版本v19.03.8。一个Ubuntu linux18.04 的Docker 镜像用于启动docker容器。

V8,V8.1.307,是google 开发的WebAssem⁃bly 运行时环境,它被预装在许多网络浏览器中。

WAVM,nightly/2020-05-28,是由Andrew Scheidecke 领导的一项协作项目,旨在支持浏览器之外的WebAssembly。

对于每个测试机器和运行时组合,运行了以下基准测试。每个测试50 次,并取完成时间的平均值和标准偏差。源代码和说明在GitHub上公开提供[6]。

(1)nop 测试,启动运行时环境并退出。该测试评估冷启动性能。

(2)cat-sync 测试打开一个本地文件进行读取并退出。它评估进行操作系统调用的性能。

(3)CLBG 测试,以下3 个测试标准来自Computer Languages Benchmarks Game[7],该测试为超过25 种编程语言提供众包基准程序,每个测试均计算运行时间:

fannkuch-redux,重复12次,测量索引访问到一个整数序列。

mandelbrot,重复15000 次,就是生成Man⁃delbrot集可移植位图文件。

binary-tree,重复21 次,分配和释放大量二叉树。

所有基准测试都是用C 编写的。对于Docker 测试,测试源代码由llvmv 10.0.0 工具链编译为本机二进制文件。对于WebAssembly 测试,使用Emscripten SDK v1.39.17 将源代码编译为WebAssembly字节码。

图1 显示了nop 测试WebAssembly 冷启动的执行时间,结果至少比Docker 快10 倍。WebAs⁃sembly 和V8 的启动时间都不到docker 启动时间的1/500。

图1 冷启动时间

图2 显示了cat-sync 测试的执行时间结果,WebAssembly 运行时至少比Docker 快10 倍。其中WebAssembly 表现出最好的性能。Docker 打开文件所需的时间是WebAssembly 的10 到15倍。

图2 打开和读取文件时间

表1 显示了3 个计算基准的执行时间结果。WebAssembly运行时比docker快10%到50%。

表1 基准测试执行时间 单位:秒

除了执行时间性能优势之外,WebAssembly的占用空间也比Docker小得多,Ubuntu 18.04的docker 映像为188 MB。一般来说,Webassembly运行时是FaaS的完整Docker镜像大小的1/10。

5 挑战和讨论

虽然WebAssembly 运行时在基准测试中的表现优于Docker,但也存在许多可能阻碍其应用的挑战。

首先,WebAssembly 上的编程语言支持是有限的。虽然LLVM 工具链理论上支持从20 多种语言生成Webassembly 字节码,但在实践中只有少数几种语言得到很好的支持。目前,C/C++、Rust 和Assembly Script 是支持WebAs⁃sembly 的最好的编程语言,这意味着开发人员如果需要使用基于WebAssembly 的FaaS 服务,就需要用这些语言编写相应的函数,来执行需要的结果[8]。

其次,与容器docker 和微型虚拟机相比,WebAssembly 具有不同的模型来访操作系统。WebAssembly 可以访问一些系统特性,例如网络和多线程管理,因为WebAssembly 对这些资源的访问受高级安全策略的约束(即基于能力的安全性),所以可以兼具高性能和安全性。在本研究中,除了简单的文件操作之外,并没有评估WebAssembly 运行时的性能。多线程I/O 是当前应用程序的一个重要方面,随着相关Webas⁃sembly规范的成熟,多线程I/O将是未来研究的主题[9]。

最后,目前没有针对WebAssembly 运行时的行业标准管理和编排工具。大多数使用自主开发的解决方案来按需启动和停止WebAssem⁃bly 运行时环境。未来预计随着WebAssembly 使用率的增加,此类编排管理工具将会出现。

猜你喜欢

开发者代码容器
容器倒置后压力压强如何变
难以置信的事情
创世代码
创世代码
创世代码
创世代码
“85后”高学历男性成为APP开发新生主力军
16%游戏开发者看好VR
取米