Cloudflare有一个叫作Workers的云计算平台。与其他云计算平台不同的是,它不使用容器或虚拟机。我们认为这才是Serverless和云计算的未来。
Isolate
两年前我们遇到了一个问题。我们的功能和选项自建能力受到了限制,我们需要一种方案可以让客户自己构建功能。我们开始寻找一种让用户直接在我们遍布世界各地的服务器上编写代码的方法(当时我们有一百多个数据中心,在写这篇文章的时候有155个)。我们的系统需要安全地运行不受信任的代码,并且要求很低的开销。我们面对着一千万个站点,每秒处理数百万个请求,而且必须快速处理完毕。
我们之前用过的Lua不是运行在沙盒中,我们不能在没有监督的情况下让用户编写自己的代码。传统虚拟化和容器技术(如Kubernetes)对于每个参与者来说都是非常昂贵的。在一个位置运行数千个Kubernetes Pod需要非常密集型的资源,而在155个位置运行这么多的Pod会更加糟糕。如果有一个管理系统,那么扩展它们会比较容易,但也绝非易事。
我们最终采用了Google Chrome团队为浏览器JavaScript引擎V8开发的隔离技术Isolate。
Isolates是一种轻量级的上下文,它对变量进行分组,并允许修改这些变量。最重要的是,单个进程可以运行数百个甚至数千个Isolate,并可以在它们之间进行无缝切换。这样就可以在单个操作系统进程中运行来自多个不同用户的不受信任代码。它们启动非常快,并且不允许一个Isolate访问另一个Isolate的内存。
我们已经在JavaScript运行时上付出了一些开销,然后基本上就可以运行无限多的脚本,而且几乎没有额外单独的开销。任意给定的Isolate都可以比我在机器上启动Node进程快一百倍。更重要的是,它们消耗的内存少了一个数量级。
他们有FaaS人体工程学,只管编写代码而不用担心如何运行或扩展。同时,他们不使用虚拟机或容器,也就是说,代码的运行环境比其他形式的云计算更接近裸机。我认为,这个模型可以获得接近于在裸机上运行代码的经济性,同时又能提供一个完全Serverless的环境。
这并不是在为Workers打广告,我只是想向你展示一个图表,它反映了这种差异是多么的明显,并且说明了为什么我认为这不只是迭代性的改进,而是一种范式转变:
这些数据反映了数据中心发出的实际请求(包括网络延迟),负责处理CPU密集型的工作负载。
冷启动
不是每个人都完全理解传统Serverless平台(比如Lambda)是如何工作的。它为你的代码启动容器化进程。它用来运行代码的环境并不会比在自己的机器上运行Node更轻量级,它只是可以更好地自动扩展这些进程(有点笨拙),而自动扩展需要进行冷启动。
当需要在计算机上启动代码的新副本时就会发生冷启动。在Lambda世界中,这相当于启动一个新的容器化进程,可能需要500毫秒到10秒。你收到的任何请求最多会被搁置十秒钟,这是一种非常糟糕的用户体验。由于Lambda一次只能处理一个请求,因此在获得额外的并发请求时,必须冷启动一个新的Lambda。这意味着可能会反复出现请求延迟。如果你的Lambda无法尽快收到请求,它将被关闭,然后再重新启动。每当部署新代码时,这些事情都会再次发生,因为每个Lambda都必须重新部署。可见,Serverless并不像它标榜的那样好。
因为Workers不需要启动新的进程,Isolate只需要5毫秒就可以完成启动,这中间的延迟很难被察觉到。Isolate可以进行快速的扩展和部署,完全消除了现有Serverless技术在这方面存在的问题。
上下文切换
操作系统的一个关键特性是你可以一次运行多个进程,并在各种进程之间进行切换。这是通过“上下文切换”来实现的:将一个进程的所有内容移出内存,并将下一个进程的所有内容移进内存。
这种上下文切换可能需要100微秒。将它乘以在普通Lambda服务器上运行的所有Node、Python或Go进程时,这将是一笔很大的开销,这意味着并不是所有的CPU都用于运行客户代码,有一部分用在了上下文切换上。
基于Isolate的系统在单个进程中运行所有代码,并使用自己的机制来确保安全的内存访问。这意味着没有昂贵的上下文切换,几乎所有的CPU时间都用来运行代码。
内存
Node或Python通常运行在个人自己的服务器上,一般不会在托管了数千个他人代码和有严格内存限制的多租户环境中运行。一个不运行实际代码的基本Node Lambda将消耗35 MB内存。如果你可以像我们一样在所有Isolate之间共享运行时,内存消耗将下降到大约3 MB。
在运行用户代码时,内存通常是最大的开销(甚至高于CPU),将其降低一个数量级将极大改善经济性。
从根本上说,V8的设计是面向多租户的。它旨在在单个进程的隔离环境中运行浏览器多个选项卡中的代码。Node和其他类似的运行时并不是这么设计的,只是它们出现在了多租户系统中。
安全
在同一进程中运行多个用户代码显然需要特别注意安全性问题。如果Cloudflare自己构建隔离层可能不会这么高效,因为它需要大量的测试、模糊测试、渗透测试,以及构建具备这种复杂性的安全系统所需的资金。
这一切要归功于V8的开源特性,以及它作为地球上最安全的软件。我们还在我们的基础之上构建了一些安全层,包括各种针对定时攻击的保护措施,但V8让这种计算模型得以变成现实。
计费
我们不打算深入讨论AWS的计费问题,但仍然会提及,因为人们对这方面的问题比较感兴趣。Lambda按照运行时长来计费,按照最接近的100毫秒进行四舍五入,这意味着人们为每次执行平均多支付50毫秒的费用。更糟糕的是,他们会在Lambda的整个运行过程中计费,即使它只是在等待外部请求完成。由于外部请求可能需要数百甚至数千毫秒的时间,因此你最终可能会为这些莫名其妙的时间付费。
Isolate的内存占用空间很小,至少我们只在实际执行代码时计费。
在我们的例子中,由于开销较低,Workers的CPU周期便宜了3倍左右。提供50毫秒CPU的Worker价格为每百万个请求0.50美元,而Lambda是每百万个请求1.84美元。我认为,对于公司来说,降低3倍成本足以成为他们转向基于Isolate的供应商的动力。
网络就是计算机
亚马逊有一款叫作Lambda@Edge的产品,部署在亚马逊CDN数据中心。我确信,他们正在尽最大努力让这项技术更具吸引力,但它比传统的Lambda贵三倍,而且部署代码变更需要30分钟时间。我认为根本没有足够的理由使用它。
相反,正如我所提到的,Isolates让我们能够将每个源文件部署到155个数据中心,其经济性甚至好过亚马逊将代码部署到一个数据中心。运行155个Isolate甚至可能比单个容器更便宜,或许亚马逊收取的费用是市场可以承受的,但仍然远高于实际成本。我不知道亚马逊的经济性如何,我只知道我们对自己的经济性感到很满意。
很早之前我们就知道,要想获得一个真正可靠的系统,必须在地球的不止一个地方进行部署。而Lambda是在单个可用区域、单个地区、单个数据中心中运行。
缺点
这个世界上没有神奇的技术,每一种技术转变都有其缺点。基于Isolate的系统无法运行编译型的代码。进程级别的隔离让Lambda加载可能会用到的任意二进制文件。但在Isolate世界中,你必须使用JavaScript编写代码(我们使用大量的TypeScript),或者使用可以编译成WebAssembly的语言(如Go或Rust)编写代码。
如果你无法重新编译旧代码,就无法在Isolate中运行它们。这意味着基于Isolate的Serverless平台仅适用于不久的将来会出现的更新、更现代的应用程序。它也可能意味着遗留应用程序只能将对延迟敏感的组件迁移到Isolate上。社区也可能找到更好的方法将现有的应用程序转换为WebAssembly来解决这个问题。
英文原文:https://blog.cloudflare.com/cloud-computing-without-containers/
相关推荐:
12 月 7 日北京 ArchSummit 全球架构师峰会上,来自 Google、Netflix、BAT、滴滴、美团 等公司技术讲师齐聚一堂,共同分享“微服务、金融技术、前端黑科技、智能运维等相关经验与实践。详情点击 https://bj2018.archsummit.com/schedule