“AI 技术+人才”如何成为企业增长新引擎?戳此了解>>> 了解详情
写点什么

字节跳动 Serverless 高密度部署与 Web-interoperable Runtime 实践

作者:朱凯迪(死月)

  • 2022-12-29
    北京
  • 本文字数:4432 字

    阅读完需:约 15 分钟

字节跳动Serverless 高密度部署与 Web-interoperable Runtime实践

在 Serverless 的浪潮下,用户的运维成本越来越低,但调度的粒度还是不够细,高密度部署解决方案将函数部署粒度进一步拆分,直达容器内部,通过调度策略能够充分压榨服务器资源(CPU、内存等)。在此基础上搭配业界标准的 Web-interoperable Runtime,让用户的开发成本、运维成本进一步降低,同时提高资源利用率。


本文整理自字节跳动架构师朱凯迪(死月)在 ArchSummit 全球架构师峰会(深圳站)上的演讲分享,主题为“Serverless 高密度部署与 Web-interoperable Runtime 在字节跳动的实践”。分享主要分为四部分:1、Serverless ⾼密度部署;2、Web-interoperable Runtime;3、高密度部署在字节跳动的实践;4、未来展望。


1 Serverless ⾼密度部署


首先,我们先讲一下 Serverless 高密度部署。传统的 Serverless 有这么几个方向,一个是低门槛,然后有 Hostless、Stateless、弹性、分布式,以及事件驱动。


传统 Serverless



传统 Serverless 由于是事件驱动的,它的入口可以是 HTTP、消息队列或者定时任务,通过不同的 Triger 来触发函数,如果是 HTTP,则通过网关,如果是消息队列,则通过 MQ Consumer,最后分发到对应的函数 Instance。通常一个实例就是一个 Pod,Pod 里面通常会监听一个端口,传统 Serverless 的模型差不多就是这样的。



分层模型


我们再把它变成一个分层的模式来看,整个流量大概就是这么一个心型的脉络。流量首先进入一个统一的网关,再由第二层的 FaaS 网关去负载均衡到不同的 Pod,也就是刚才提到的函数实例,我们把这种方式称为一种二层调度,分别是机房调度或者说是 IaaS 层的调度,然后是 K8s 层的调度,相当于容器这一层的调度。在 2 层调度中,每一层都有它自己对应的交付时间,或者说弹性的时间。它们对应的交付时间分别是天级和分钟级或者秒级的交付。


交付时间会影响到 Serverless 的冷启动时间,通常在我们的实践过程中,函数的冷启动时间是不确定的,可以是几十秒,或者几秒,或者几百毫秒,这个跟不同的应用场景、不同的业务、不同的基础服务相关。其中有很多影响因素,比如设备性能、函数运行时、网络延迟、代码包大小,或者镜像大小等。总结起来,就是约等于一个容器的冷启动时间,它又影响着 Serverless 特性中非常重要的几点:一个是 Hostless,就是我们不需要管服务器;一个是 Stateless,就是无状态;以及弹性,一个函数用完,我们可以直接装垃圾筒扔掉,随起随停,用完就丢。这是我们现在 Serverless 很多情况下的一种使用方式,或者说 Serverless 本意就是想让大家这么做。流量来了马上启动起来,弹起实例,实例化出相应的函数;流量处理完了就马上删掉。这个做法对函数的冷启动有非常高的要求,冷启动的优化是在 Serverless 中大家需要去探索的一个课题。


高密度部署

冷启动优化


冷启动的优化方式有很多。对于供应商来说,可以更换设备提高一些性能,或者提升它的整个网络架构。对于业务方来说,可以用更轻量级的运行时。比如,如果它原来用 Java 之类的,可以换成 Node,也可以去合理组织函数代码,让函数更轻量,类似于微服务的方式。但是业务方不管怎么优化,最终启动时间还是约等于容器的冷启动时间。这个时候就有一个问题了,既然冷启动速度约等于容器时间,有什么东西可以比容器更快的?答案是有的,比如说弹起一个进程的时间肯定要比弹起一个容器的时间快,当然也有可能还有其它的方式,比如进程直接起好了,我们用线程去跑。所以我们在高密度部署里面,就有了两种方案,分别是进程和线程。



我们分别从四个维度对这两种方案做了比较,发现它们不同方面各有优劣。但我既要启动速度又要安全性,我们在进程的模式上加了一些黑魔法,让它的启动速度变得非常快,可以达到亚毫秒级别(≤ 1 毫秒)的启动。


三层调度


我们最终选了进程做高密度部署,它是一个三层调度,比之前的二层调度多了一层,就是在容器内部多了一个进程或者线程级别的调度,这个调度的交付时间可以做到非常快,到毫秒级甚至是亚毫秒级。



由于多了一层调度,之前的那个心型的脉络就变成了一个方块的脉络,流量从统一网关进到 FaaS 网关,再到 Pod,到了 Pod 之后,又多了一层节点,就是在容器内部又多了一个负载网关或者调度器,再流到不同的函数实例上去,这就是我们整个高密度部署的三层调度模式。

Executable as an Image 与 Process as a Container


业务方一般不想做运维的事,他们会觉得评估资源很烦,于是就怎么大怎么来,导致产生非常大的资源浪费。为什么业务方往往不愿意做这个评估?因为对于他们来说,估少了流量机器扛不住,如果要扩容,需要时间比较长,这个时候万一系统挂了就不好了,哪怕有熔断限流这些机制,部分用户不可用也是不好的。而高密度部署就可以帮他们解决问题,反正弹的快,可能一毫秒都不用就把函数弹起来了,流量来了马上弹起来,不用估直接用就好。这样就可以提高资源利用率。


弹性变高了,运维降低了,资源利用率也提高了,还会有什么问题呢?比如一个容器里面部署了多个函数,如果它们乱搞,最后一下子炸了,但没有做一些相应的资源限制和资源隔离,各函数之间可能就会相互影响。我们参考了云原生的 OCI 标准,提出 EaaI(Executable as an Image) 和 PaaC(Process as a Container),相当于跟 Docker 镜像和 Docker 容器对标,把可执行文件看成是镜像,把进程看成是容器。在启动的时候,可以理解为原来部署一个 Docker 容器,现在变成部署一个高密度的容器,高密度容器就是 PaaC,对应使用的二进制就是一个镜像,就是 EaaI。本质上它们就是一个可执行文件和进程,只不过我们在这中间加上了 OCI 的规范。开源社区有一个叫 RunC 的容器运行时,在 K8s 体系中容器可以通过 RunC 去启动,但是 RunC 只是用于启动容器的,并不能启动高密度容器。我们最后自研了一个叫 iku 的容器运行时,它是遵循 OCI 规范的容器运行时,用于启动高密度容器。而且我们的高密度容器也通过它做了一些资源的限制以及资源的隔离,就是规定一个容器只能用多少 CPU、多少内存,这个跟容器的限制是一样的。

2 Web-interoperable Runtime


Web-interoperable Runtime(Winter)是我们用于搭配高密度部署而研发的新函数运行时。首先解释一下,什么叫 Web-interoperable Runtime,它在以前有一个更糙且不严谨的名字,叫做 V8 Worker。因为好多厂商都基于 V8 做了 JavaScript 的运行时,但是后来经过标准化规范化之后,国际上的几家厂商就一起给它起了一个新的名字,并且开始做一些标准化的事情,组建了一个组织叫做 WinterCG(Web-interoperable Runtimes Community Group),它是由几家国际公司联合起来搞的 W3C 下的一个社区组,致力于做 Web-interoperable Runtime 标准化。


这里有一个核心的单词叫 interoperable,就是互通性,什么是互通性?就是运行时之间是可以互相替代、互相兼容的。各种浏览器之间就是 interoperable,经过标准化之后,大家 API 长的都一样,这就是所谓的互通性。Node.js 几个大版本也是开始往 Winter 上靠,市面上的 Winter 除了 Node.js 之外还有 Deno、CloudFlare Workers、Oxygen + Hydrogen 等等。我们自己也有一套自研的 Winter 运行时,叫 Hourai.js,它是用于我们的高密度部署的。


Winter 相较于 Node.js 来说,有一些很好的优势,比如低门槛,因为写 JS 的前端开发者们更熟悉浏览器 API。选择 Node.js 你要自己实现一个服务器,你要监听端口,自己去实现整个 HTTP 服务器,除此之外,你还要搞它的 PM2、运维、部署,等等。如果上了 Winter 就简单了,我们不需要监听端口,只需要监听 Fetch 事件,之后直接把它上到高密度部署,其他什么事都不需要管,它直接会触发事件,我们只要写里面的逻辑就可以了。



回顾一下,高密度部署是希望可以解决随起随停、用完就丢的问题,主打的是轻量以及启动速度快。Node 冷启动大概需要两百毫秒,那么 Serverless 函数至少要两百毫秒往上了,我们当然也可以通过池化,或者 snapshot 之类的来进行优化,但是为什么这么麻烦,为什么不直接一点?我们 iku 里面就提供了一个 ASSS 能力,即 Active Safety Strip Snapshot,专攻启动速度,最终达到了小于一毫秒。


3 高密度部署在字节跳动的实践


我们有一组实践数据,某服务迁移到线程级高密度部署,CPU 核数从原来 287 降低到 24,内存从原来 574G 降低到 39G。所以,高密度部署就约等于更高的资源利用率 + 更快的调度速度 + 更低的运维成本。



我们也做了其它的一些事情,比如往云原生上去靠,实现了 OpenTelemetry 这一套 API,Hourai.js 通过可观测性相关 API 传到它的 Agent,再到 Collector,最后再传到我们内部的一些系统,这就是整个 API 链路。



在多运行时调用上面,我们也有一套实践,就是遵循了 Dapr,在拿到 Dapr 的实例之后,直接 Invoke,把对应的参数传进去,不需要管多运行时的那些 SDK,这个就是云原生给我们带来的好处,大家既然上了 Serverless 干脆就全套上云原生。


我们还针对不同的场景做了抽象,它可以根据不同的业务需求来进行扩展,对上可以去接不同的网关层,对下可以接到不同的 IaaS 层,比如说私有化部署,它可能没有字节内部的 FaaS 环境,但很方便就能把我们的高密度部署部到类似于 ECS 的环境。



Serverless 还有一个非常合适的场景,就是流程编排。Serverless 流程编排是流程里面不同的 Function,一个一个节点流过去,它的高密度部署相较于传统的来说更适合这个方式,就是一个函数流过去,马上就启动这个函数,用完马上就丢,非常适合流程编排。因为高密度部署就是更高的资源利用率,更快的调用速度,以及更低的运维成本。因为它弹的更快,流程编排内容非常细粒度的东西就非常好上;然后更低运维成本对于编排的用户来说,关心的就是只要写下一小段代码片段就好了;更高的资源利用率也是毋庸置疑的。


关于 APP 网站,首屏速度非常重要,因为首屏时长的长短等同于一个用户的转化率,如何优化首屏时间也是一个亘古不变的课题。我们目前正在跟字节跳动的前端框架团队合作,就是用 Modern.JS,加上边缘机房,加上高密度部署以及 Winter,整理出了一套边缘上的高密度部署渲染方案,以此来提高首屏渲染的速度。

4 展望未来


未来在高密度部署方面,我们可以让 K8s 直接穿透我们的一个调度,穿透到容器内部来。因为我们也是遵循 OCI 标准的,理论上 K8s 可以直接调进来,不用先调到容器,容器再调进来,它可以直接穿透进来,启动我们的高密度容器,甚至,它可以抛弃容器,直接部署到物理机上,作为高密度容器让 K8s 直接调度,甚至可以替换掉 K8s,直接由我们的 iku 做整个调度。


在 Winter 这一方面,我们要做一个更极致的 ASSS 能力,以及分布式的极速启动能力,我们现在的 ASSS 能力都是以单机为单位的。另外,我们可以与社区一起去推进 WinterCG 的发展,往后会对外进行 ToB,或者之后有可能会去做一些开源的事情。

相关阅读:

如何用 7 分钟击破 Serverless 落地难点?


Serverless Devs 重大更新,基于 Serverless 架构的 CI/CD 框架:Serverless-cd


应用 Serverless 化,让业务开发心无旁骛


Serverless 的前世今生

2022-12-29 15:317029

评论

发布
暂无评论
发现更多内容

小程序插件的生态丰富,加速开发建设效率

Speedoooo

小程序 小程序容器 小程序插件

半夜赶工制作简报的我好想说 : 确定了,最终稿就是这样

叶小鍵

如何通过DBeaver 连接 TDengine?

TDengine

数据库 tdengine Dbeaver

基于深度学习的裂缝检测技术

阿炜小菜鸡

8月月更 裂缝监测

前端面试高频20道手写题(二)

helloworld1024fd

中原银行实时风控体系建设实践

Apache Flink

大数据 flink 编程

主流跨端技术一览

Speedoooo

前端框架 小程序容器

IIR数字滤波器设计(数字信号处理)

Five

matlab 过滤器 8月月更

技术分享| 融合调度系统中的电子围栏功能说明

anyRTC开发者

音视频 快对讲 语音对讲 视频对讲 电子围栏

数据湖(二):什么是Hudi

Lansonli

数据湖 8月月更

软件成分分析:手握5大能力守护软件供应链安全

华为云开发者联盟

云计算 安全 华为云

【云原生】jenkins部署docker镜像到远程服务器

青芒果

云原生 CODING Linxu docekr 8月月更

ABAP-OOAVL模板程序

桥下本有油菜花

abap

SpringBoot 发送邮件

开源 SpringBoot 2 8月月更

数据湖(一):数据湖概念

Lansonli

数据湖 8月月更

8大软件供应链攻击事件概述

SEAL安全

开源 DevOps DevSecOps 软件供应链安全 软件供应链攻击

七日算法先导(二)——双指针

工程师日月

8月月更

前端面试高频20道手写题

helloworld1024fd

看我如何用多线程,帮助运营小姐姐解决数据校对系统变慢!

华为云开发者联盟

后端 开发

数据湖(三):Hudi概念术语

Lansonli

数据湖 8月月更

分享一个Chrome控制台数据获取的例子

睡着了去做梦

Go Chrome开发者工具

React高频面试题合集(二)

helloworld1024fd

React

受邀出席Rust开发者大会|Rust如何助力量化高频交易?

非凸科技

量化策略 量化交易

基于threejs的商品VR展示平台的设计与实现思路

Five

js vr three.js 签约计划第三季 8月月更

如何在Linux中不解压就能查看压缩包中的内容,这13个命令非常强!

wljslmz

Linux 签约计划第三季 8月月更

react高频面试题总结(一)

helloworld1024fd

React

react常见面试题

helloworld1024fd

React

FinClip | 来了, 2022 年 7 月更新大盘点

FinClip

Vite2 + Vue3 + TypeScript + Pinia 搭建一套企业级的开发脚手架

小周先生

开源 Vite2 vue3.0 #开源 8月月更

开源一夏 |Spring boot 自动配置原理

叶秋学长

开源 8月月更

实践GoF的设计模式:迭代器模式

华为云开发者联盟

后端 开发

字节跳动Serverless 高密度部署与 Web-interoperable Runtime实践_大前端_InfoQ精选文章