作者 | 阿里中间件高级技术专家 许晓斌
《Maven实战》作者,曾负责 AliExpress 微服务架构演进,现在负责阿里集团 Serverless 技术研发落地。
导读:从 2016 年 AWS 发布 Lambda 以来,全世界的开发者和云厂商对 Serverless 的热情在不断高涨。假设不想在开发应用程序并将其部署在服务器上的过程细节上花费精力,是否有一种简单的架构模型能够满足我们这种想法呢?答案已经存在,这就是今天软件架构世界中新鲜但是很热门的一个话题——Serverless(无服务器)架构。本文作者将利用自身多年的研发经验,带领我们深入了解 Serverless 行业的发展!
《喧哗与骚动》是我喜欢的作家威廉·福克纳的一部小说,小说用多个家庭成员的意识流,从不同的视角描绘了一家三代的悲剧。这部小说有意思的地方在于:对于同样一件事情,从不同人跳跃的意识中能看到迥然相异的景象。
今天大家理解 Serverless 也有点这个意思,因此我以此为题,展开分析。文章只代表作者本人观点。
Serverless is like teenage sex
不知道大家有没有听过这样的话:
Big data is like teenage sex: Everyone talks about it, nobody really knows how to do it, everyone thinks everyone else is doing it, so everyone claims they are doing it.
我们把 Big data 换一下: AI is like teenage sex: Everyone talks about it, nobody really knows how to do it, everyone thinks everyone else is doing it, so everyone claims they are doing it.
我们把 AI 换成 Serverless: Serverless is like teenage sex: Everyone talks about it, nobody really knows how to do it, everyone thinks everyone else is doing it, so everyone claims they are doing it.
从中可以总结出以下几点:
所有人都在说 Serverless;
几乎没人知道怎么落地 Serverless;
但是大家都觉得其他人在大力做 Serverless;
所以大家都宣称自己在做 Serverless。
Serverless 和很多词如微服务一样,是没有精确定义的,也没有事实的标准。什么是事实标准?Kubernetes 是事实标准;对 Java 程序员来说 Spring Boot / Spring Cloud 是事实标准。
事实标准就是一种思想/方法论得到了广泛落地,占领了市场。落地通常意味着两个点:
它是开放(开源)的。因此不会有 vendor lock-in,所有人可以放心用;
有大量的成功案例。很多人将其用到关键的商业系统中,因此得到了广泛验证。
Serverless 的愿景
下面是来自 Google Trends 的一个图,其中红色是 Microservices,蓝色是 Serverless。
从 2016 年 AWS 发布 Lambda 以来,全世界的开发者和云厂商对 Serverless 的热情在不断高涨,这说明大家对 Serverless 所描绘的愿景都非常 buy in。这个愿景是什么呢?
愿景是无服务器?但工程师们都知道服务器本质上是存在的,最多是加一层抽象,让我们看不到服务器,但它依旧很好的发挥作用。
我个人觉得有关 Serverless 愿景,描绘最清楚的是一个比喻,这个比喻来自 UC Berkeley 在今年2月发表的那篇论文[1]:
简单来说就是:我们今天对云资源的操作方式,就类似于几十年前早期程序员写汇编的方式。
如果你没写过/学过汇编语言,或者已经忘了汇编语言,我特地找了本书拍了一段内容下来:
是不是对图中的这些寄存器、栈、程序计数器、以及相关的汇编指令感到很陌生了?如果让你用这样的语言写业务逻辑,那效率必然会变得非常低。
幸好我们有 Java,Go,JavaScript 这样的高级语言,而这些高级语言还配套了相关的编译器/虚拟机,编译器/虚拟机能够高效地把面向业务的高级语言翻译成面向机器的汇编/机器码。
今天,虽然基本的计算机体系结构没有发生本质的变化,但我们的程序所运行的环境,相比较20年前,已经发生了本质的变化。20 年前的程序大都跑在单机上,今天我们的程序都要为了跑在云上而设计了。
为了让程序跑在云上,我们就需要配套的工作,包括云资源(容器、缓存、队列)的申请和回收、包括弹性伸缩的控制,等等。这些事情和业务逻辑没有任何关系,但研发/运维同学却为此花费了大量的时间。
我想做一个不太成熟的类比:
单机时代,操作系统管理了硬件资源,贴着资源层,高级语言让程序员描述业务,贴着业务层,编译器/VM 把高级语言翻译成机器码,交给操作系统;
今天的云时代,资源的单位不再是 CPU、内存、硬盘了,而是容器、分布式队列、分布式缓存、分布式文件系统。
云上的 OS 这个角色,基本上可以说是被 Kubernetes 生态给占了,那么云上的编译器/VM 呢?开发语言和框架呢?好像还没有。
今天我们把应用程序往云上搬的时候(a.k.a Cloud Native),往往都会做两件事情:
第一是把巨型应用拆小,微服务化;
第二就是摇身一变成为 yaml 工程师,写很多 yaml 文件来管理云上的资源。
本质上大家都在把面向单机体系架构编写的应用程序,硬搬到云体系架构上。我认为这里存在两个巨大的 gap,这两个 gap 在图中用灰色的框表示了:
1. 编程语言和框架;
目前主流的编程语言基本都是假设单机体系架构运行的,面对分布式问题的时候,再叠一层框架上去。其对应的资源也依旧停留在单机体系结构的那些资源上(当然这里是有例外的,比如 erlang/OTP 天生就是为分布式设计的)。
云时代,首先基本的资源单位发生了变化,从原来的 cpu、内存变成了容器、函数、分布式队列等等;其次,云天生分布式,因此单机时代大行其道的同步模型就不再适合。
2. 编译器。
程序员不应该花大量时间去写 yaml 文件,这些面向资源的 yaml 文件应该是由机器生成的,我称之为云编译器,高级编程语言用来表达业务的领域模型和逻辑,云编译器负责将语言编译成资源描述。
我个人很看好 Erlang 的 Actor 模型,这个模型在其他语言上也有实现,例如语法参考 Ruby 并运行在 Erlang OTP 上的 Elixir,JVM 上的 Akka,以及 .NET 上的 Orleans。
不同于其他语言的设计,Actor 模型从一开始就是基于分布式的前提做的设计,因此这种模型如果把其对应的资源管理换成纯粹的云资源管理,我觉得是有极大可行性的。
Write locally, compile to the cloud.
大家在忙什么
除了抬头看天,说了一大堆美好的愿景,还得低头走路,先看看这条路上其他人在做什么。我整理了一下最近一年 Serverless 领域行业发生的一些比较重要的事件。
公众号后台回复关键字 "serverless" 获取 Serverless 领域近一年行业发展回顾。
为了能够稍微清晰一点地去看这一大堆的产品和技术,我简单的把 Serverless 领域做的事情分了三个层,自下而上分别是资源层、DevOps 层和框架及运行时层。
资源层关注的是资源(如容器)的生命周期管理,以及安全隔离。这里是 Kubernetes 的天下,Firecracker,gVisor 等产品在做轻量级安全沙箱。这一层关注的是如何能够更快地生产资源,以及保证好安全性。
DevOps 层关注的是变更管理、流量调配以及弹性伸缩,还包括基于事件模型和云生态打通。这一层的核心目标是如何把运维这件事情给做没了(NoOps)。虽然所有云厂商都有自己的产品(各种 FaaS),但是我个人比较看好 Knative 这个开源产品,原因有二:
第一是其模型非常完备;
第二是其生态发展非常迅速和健康。很有可能未来所有云厂商都要去兼容 Knative 的标准,就像今天所有云厂商都在兼容 Kubernetes 一样。
以下是 Knative 近一年的贡献者及贡献数量的增长情况,数据来自演讲「Knative a Year Later: Serverless, Kubernetes and You」。[2]
框架和运行时层呢,由于个人经验所限,我看的仅仅是 Java 领域,其实核心的还是在解决 Java 应用程序启动慢的问题(GraalVM)。当然框架如何避免 vendor lock-in 也很重要,谁都怕被一家云厂商绑定,怕换个云厂商要改代码,这方面主要是 Spring Cloud Function 在做。
刚需在哪里
产品想要成功,需要有核心竞争力,这个核心竞争力往往就是,你解决了一个用户很头疼、但其他产品没有解决的问题。我姑且把这样的问题称为用户的刚需。那么 Serverless 能解决哪些用户的什么刚需呢?我先对用户做一些简单的分析:
很多技术产品基本都是经历了如下四个阶段:
初创期:一个小团队围绕新的业务做试错,从无到有,技术上什么能快速上线用什么;
这个时候团队规模很小,可能两三个人,所有代码放在一个应用内,不需要分布式,不需要隔离。
成熟期:业务成功了,用户在不断增多,业务也变得越来越复杂;
这个时候团队的规模增长到数十到上百人,团队还处在一个部门,相互之间有足够的信任,沟通带宽也有足够的保证。一个应用的模式已经不能满足协作的需要,架构师开始做应用拆分,系统成了分布式的,按照业务的划分做了进程级别的隔离。
平台期:业务太成功了,就希望把已经沉淀的能力赋能给其他类似的业务;
相比较于成熟期,这时候有了一些新的变化。首先是参与开发的人数增长得更多了,往往是数百上千;其次大多数参与开发的成员已经不再是核心产品团队的成员,他们往往在不同部门了,相互之间的信任已经大大减弱,沟通带宽也开始显著变窄。
由于核心团队对于其他部门的开发缺乏组织管控能力,因此技术上的隔离要求被提上优先级,以避免平台上的开发者不小心拖垮平台本身。
伴随着隔离,成本的问题也被提上日常,当平台上数百个插件和平台本身跑在同一个进程内的时候,资源天然是被复用的,只要模糊地计算下整体即可;当数百个插件被隔离到独立的容器中运行的时候,他们的资源占用就需要额外的调度系统去控制和优化。
云产品期:平台太成功了,就希望做成云服务,赋能社会上类似的业务,发挥更大的价值。
如果说在平台期,隔离还只是个重要但非必须的要求的话(很多平台就没有真正做好隔离),云产品期的产品必须具备非常强的隔离能力。
平台期做隔离最大的诉求是稳定性(不被平台上的开发者搞垮整个平台),而云产品期做隔离的最大诉求是安全性。
正如图中所示,产品上的开发者已经和产品团队不在一个组织了,而且这样的开发者还可能是恶意的,因此除了容器的隔离,还需要虚拟机级别的隔离,网络的隔离等等。
随着技术产品由小长大,不断成功,参与的开发者不断增长,核心团队对这些开发者的控制力越来越弱,沟通带宽不断缩减,信任不断降低,进而导致了稳定性和安全的风险不断上升,这就要求隔离能力不断加强。而随着隔离的引入,以及使用资源的不断增长,成本就成了一个不得不面对的问题,为了更优地分配资源,解决成本问题,就对调度提出了要求。
因此,对于处在平台期和云产品期的产品来说,技术上的隔离能力及调度能力是他们的刚需。
框架和运行时的创新
前面所说的刚需都是集中在稳定性、安全性及资源成本的角度来讨论的。除此之外我们还需要讨论另外一个话题,那就是开发效率,而开发效率具体到技术是体现在框架上的。
我们可以进一步的把框架分成两类:
面向技术问题提升开发效率的框架:如 Spring 通过依赖注入解决对象组装问题;HSF 解决分布式同步通讯问题;RocketMQ 解决分布式异步通讯问题;Hystrix 解决分布式通讯引入的网络不可靠问题等等。
通过使用这些框架,技术的天然复杂度在很大程度被屏蔽掉了。
面向业务问题提升开发效率的框架:阿里的很多业务平台团队都会根据自己的场景(如交易、店铺、供应链)开发业务型框架,赋能开发快速迭代业务。
通常,面向技术问题的框架会有一个团队研发,而面向业务问题的框架则由各类业务平台团队提供,这再一次证明了康威定律的正确性。康威定律翻译成中国的土话差不多就是“屁股决定脑袋”,技术型团队不愿意碰业务问题,而业务平台团队的框架在解决技术问题方面也显得没有技术团队专业,最终的结果是:两种框架割裂得比较厉害。
大家可能听过这么一个故事:
有一条恶龙,每年要求村庄献祭一个处女,每年这个村庄都会有一个少年英雄去与恶龙搏斗,但无人生还。又一个英雄出发时,有人悄悄尾随。龙穴铺满金银财宝,英雄用剑刺死恶龙,然后坐在尸身上,看着闪烁的珠宝,慢慢地长出鳞片、尾巴和触角,最终变成恶龙。
虽然看起来很夸张,但在我看来,这一定程度上体现了一些大中型研发组织主流框架的现状:这些框架在组织发展的历史上发挥了极其重要的作用,然而到了今天,随着云服务不断地成熟,大家都在提云原生,都基于云在构建业务系统的时候,需要框架还在强制用户绑定语言(如 Java),还没做好服务化,把逻辑塞进用户的应用中。有的甚至要求用户的代码必须部署到平台的巨型应用中。
这些限制短期内实现了业务目标,交付了业务价值,但从长期看基本上浇灭了业务开发做框架创新的热情,他们更习惯于等待“位于正确定位的团队”去解决问题,而“处于正确定位的团队”同学呢,可能一时半会还没感受到那些问题。
不出意外的话,专注组织内短期业务价值的框架,被推到云上、推到社区、面向更普适通用诉求的时候,获得的认可就会差很多。
传统的框架和运行时,只管理单机层面的资源,而当所有人都用云服务构建自身业务的时候,框架和运行时需要管理的就不再是单机资源,而是云资源了。
在这方面行业里已经有了不少产品,比较知名的有 Terraform[3] 和 Pulumi[4],但我觉得还不够,我觉得理想的云原生框架应该是这样的:
能够帮助开发屏蔽云资源的管理。开发都不喜欢像写汇编一样写 yaml,因此框架需要负责资源的分配、回收,编排等等;
纯异步的,事件驱动的。这是云天生的分布式特性决定的,如果编程语言范式还是同步的模型,这个框架就没法实现了;
没有 vendor lock-in。不绑定实际的云厂商,唯有厂商中立的开发框架才能被广泛使用,框架定义了编程 API,具体的厂商可以提供相关的 driver;
同时具备云资源管理和大规模软件开发必须的编程范式。这里的编程范式可能描述不当,但我找不到更好的词,面向对象设计是最主流的编程范式,Spring 就是围绕这个编程范式展开的。在一个框架中解决两个问题,会给开发极好的体验。
小结
Serverless 这个领域看起来极其美好,一旦深入去做了才发现实际非常复杂。这个复杂体现在涉及的工程技术比较广,也体现在用户的期望差异很大,更体现在大家对未来的判断还有很大的差异。
在和团队一起深入这个领域的时候,我也需要不断整理自己的所闻所见、所思所想,因此我计划产出一系列文章,拿出来和大家分享,和大家探讨,这是第一篇,有兴趣的同学可以进群讨论。
——图书推荐——
——关注本号——