面临的挑战
即使Serverless架构在如今发展迅速,被更多人认为是真正意义的云计算,甚至在2020年的云栖大会上,Serverless被再次断言“将会引领云计算的下一个十年”,但是Serverless仍然有着自己的劣势,在如今的发展阶段,Serverless架构仍然面临着诸多挑战。在2019年UC Berkeley的文章《Cloud Programming Simplified: A Berkeley View on Serverless Computing》中,针对Serverless架构总结出了包括Abstraction challenges、System challenges、Networking challenges、Security challenges、Computer architecture challenges等在内的挑战:
Abstraction challenges:
- 资源需求(Resource Requirement):通过今天的Serverless产品,开发人员可以指定云功能的内存大小和执行时间限制,而不是其他资源需求。 这种抽象阻碍了那些想要更多控制指定资源的人,例如CPU,GPU或其他类型的加速器;
- 数据依赖(Data dependencies):今天的云功能平台不了解云功能之间的数据依赖性,更不用说这些功能可能交换的数据量。 这种无知可能会导致次优放置,从而导致通信模式效率低下;
System challenges:
- 临时性存储(Ephemeral Storage):为Serverless应用提供临时存储的一种方法是使用优化的网络栈构建分布式内存服务,以保证微秒级的延迟;
- 持久性存储(Durable Storage):与其他应用程序一样,Serverless数据库应用受到存储系统的延迟和 IOPS 的限制,但它也需要长期的数据存储和文件系统的可变状态语义;
- 协调服务(Coordination/signaling service):功能之间的共享状态通常使用生产者 - 消费者设计模式,这需要消费者在生产者可以获得数据时立即知道;
- 最小化启动时间( Minimize startup time): 启动时间有三个部分(1)调度和启动资源以运行云功能,(2)下载应用软件环境(例如,操作系统,库)以运行功能代码,以及(3) 执行特定于应用程序的启动任务,例如加载和初始化数据结构和库。 资源调度和初始化可能会因创建隔离的执行环境以及配置客户的VPC和IAM策略而产生显着的延迟和开销;
- Networking challenges:云功能可能会对流行的通信原语(如广播,聚合和混洗)产生巨大的开销;
- Security challenges:Serverless架构重新安排了安全责任,将其中许多人从云用户转移到云提供商,而没有从根本上改变它们。 但是,Serverless架构还必须解决应用程序分解多租户资源共享中固有的风险。Serverless架构重新安排了安全责任,将其中许多人从云用户转移到云提供商,而没有从根本上改变它们。 但是,Serverless架构还必须解决应用程序分解多租户资源共享中固有的风险;
- Computer architecture challenges:主宰云的x86微处理器性能提升速度缓慢;
当然,这篇论文对Serverless架构面临的挑战相对来说是比较抽象的,但是就目前的工业界实际情况来看,这些挑战依旧普遍存在,也是当今众多云厂商不断努力解决的问题。站在Serverless开发者角度而言,将论文中的挑战与开发者最为关注的几个问题结合起来,可以认为Serverless架构目前所面临的挑战包括不限于冷启动问题严重、厂商锁定严重、配套资源不完善等。
冷启动问题
所谓的冷启动问题,指的是Serverless架构在弹性伸缩时可能会触发环境准备(初始化工作空间)、下载文件、配置环境、加载代码和配置、函数实例启动完整的实例启动流程,导致原本数毫秒/数十毫秒可以得到相应的请求需要在数百毫秒/数秒才能得到响应,进而影响业务性能的情况。
正如前文所说,任何事物都是有两面性的,在Serverless架构具备弹性伸缩的优势特性时,相对Serverful架构而言,也引入了一个新的问题:Serverless架构所拥有的弹性伸缩性能问题堪忧,即冷启动问题严重。
Serverless架构下,开发者提交代码之后,通常情况下,代码只会被持久化并不会为其准备执行环境,所以当函数第一次被触发时会有一个比较漫长的准备环境的过程,这个过程包括把网络的环境全部打通、将所需的文件和代码等资源准备好,这个从准备环境开始到函数被执行的过程,被称为函数的冷启动。由于Serverless架构具有弹性伸缩的能力,Serverless服务的供应商会根据用户服务的流量波动进行实例的增加或缩减,所以函数就可能涉及到频繁准备新的环境、下载函数代码、启动实例来应对不断产生的请求。
如图所示,当Servelress架构的FaaS平台中某函数接收到触发请求,FaaS平台将会根据具体情况进行实例的复用或者新实例的启动:
如图所示,当有空闲且符合复用要求的实例时,FaaS平台将会优先使用,这个过程是通常所谓的热启动过程,否则FaaS平台将会启动新的实例来应对此时的请求,这个过程则是对应的冷启动过程,Serverless架构的这种自动的零管理水平缩放,将持续到有足够的代码实例来处理所有的工作负载为止。这其中“新实例的启动”,则包括了初始化工作空间、下载文件和配置环境、加载代码和依赖、函数实例启动等几个步骤,相对于热启动在数毫秒或者几十毫秒内的启动,冷启动所多出来的这几个步骤耗时可能是百毫秒甚至数秒,这种在生产时出现的“新实例的启动”,并导致业务响应速度受到影响的情况,通常就是大家所关注的冷启动带来的影响。
综上所述,不难分析和总结出冷启动常见出现的场景:
- 函数的第一次启动:函数部署后的第一次启动,通常是不存在已有实例,所以此时极容易产生冷启动的情况;
- 并发的情况下:当前一个请求还没有完成,就收到了新的请求,此时FaaS平台会启动新的实例来应对新的请求,进而出现冷启动的问题;
- 前后两次触发间隔太久:函数的前后两次触发时间间隔超过了实例释放时间的阈值,也会触发函数的冷启动;
就目前来看,Serverless架构所面临的冷启动挑战虽然严峻,但并不致命,因为各个云厂商都正在努力推出冷启动的解决方案,包括不限于实例的预热、实例的预留、资源池化等。
厂商锁定严重
所谓的厂商锁定严重,指的是Serverless架构在不同厂商表现形式是不同的,包括产品的形态,功能的维度,事件的数据结构等,所以一旦使用了某个厂商的Serverless架构,通常意味着FaaS部分和相对应的配套后端基础设施也都要使用该云厂商的,一旦想要进行多云部署、跨云厂商迁移等将会困难重重,成本极高。
众所周知函数是由事件触发的,所以FaaS平台与配套的基础设施服务所约定的数据结构往往会决定函数的处理逻辑,如果每个厂商相同类型的触发器所规约的事件结构不同,那么在进行多云部署、项目跨云厂商迁移时就会面临巨大的成本。以AWS Lambda、阿里云函数计算以及腾讯云云函数为例,可以通过对对象存储事件的数据结构进行对比:
通过图的对比,不难发现三个云厂商关于同样的对象存储触发器的数据结构是完全不同的,这就导致我们在进行对象存储事件关键信息的获取方法不同,例如同样是获取触发对象存储事件的原始IP:
按照AWS的Lambda与S3之间规约的数据结构,获取路径为:
sourceIPAddress = event["Records"][0]["requestParameters"]["sourceIPAddress"]
按照腾讯云的SCF与COS之间规约的数据结构,获取路径为:
sourceIPAddress = event["Records"][0]["event"]["requestParameters"]["requestSourceIP"]
按照阿里云的FC与OSS之间规约的数据结构,获取路径为:
sourceIPAddress = event["events"][0]["requestParameters"]["sourceIPAddress"]
由此可引申出,当开发者开发一个功能,在不同云厂商所提供的Serverless架构中实现,涉及到的代码逻辑、产品能力均是不同的,甚至包括业务逻辑的开发、运维工具等也是完全不同的。所以想要跨厂商进行业务迁移、业务的多云部署,将会面临极高的兼容性成本、业务逻辑的改造成本、数据迁移的风险、多产品的学习成本等;
综上所述,由于目前没有完整的、统一的且被各个云厂商所遵循的规范,就导致不同厂商的Serverless架构与自身产品、业务逻辑绑定严重,非常不利于开发者的跨云容灾,跨云迁移。目前来看,Serverless架构厂商锁定严重的问题,也是如今开发者抱怨最多,担忧最多的问题之一,当然就该问题而言,无论是CNCF或者是其他的一些组织、团队都正在努力在上层通过更规范、更科学的手法进行完善和处理,以上文举例的Event规范,就有CNCF发起的CloudEvents项目正在努力解决。
配套资源不完善
所谓的配套资源不完善,指的是Serverless架构的核心思想之一是将更多更专业的事情交给云厂商来做,但是在实际过程中,云厂商会碍于一些需求优先级等问题,以及自身业务素质等问题,没有办法做更多“在Serverless架构中该做的事情”,所以就导致在开发者对Serverless架构项目开发、运维过程中困难重重,抱怨不断。
在Serverless架构飞速发展的过程中,各个厂商也在努力完善自身的配套资源和设施,以来提升开发者的幸福感。但是尽管如此,Serverless架构还是有很多的配套资源和设施并不完善,并不能让开发者可以更顺利的完成Serverless应用的开发、更轻松的对Serverless应用进行运维。最主要表现在几个方面:
- 配套的开发者工具复杂多样,且功能不完善:就目前情况来看,并没有绝对统一/一致的Serverless开发者工具,每个厂商都有自己的开发者工具,而且使用形式,行为表现并不相同,这就导致了开发者在开发前的调研、开发中的调试、部署后的运维等多个层面面临很严峻的挑战;另外绝大部分的Serverless开发者工具更多是资源编排、部署工具,并不能真正意义上称之为开发工具、运维工具,尤其在开发态的调试如何保证线上线下环境的一致性;如何在运维态可以快速的对业务进行调试;如何更简单的排查错误,定位问题......等方面并没有统一的、完整的方案,这就导致Serverless架构的学习成本、使用成本对开发者来说会变的非常高;
- 配套的帮助文档、学习资源并不完善,学习成本过高:就目前情况来看,Serverless架构的学习资源相对来说是匮乏的,无论是从文字、视频、实验等角度,还是从厂商提供的案例、教程、最佳实践等方面,Serverless架构都是没有完善的学习资源和参考案例。比较具体的例子包括在Serverless架构下如何上传大文件;在Serverless架构下如何进行连接池管理;在Serverless架构下如何尽可能的降低冷启动带来的影响......,正是由于Serverless学习资源比较少,开发经验案例比较少,导致开发者在学习阶段很闹找到适合自己的学习资源,开发过程中经常会遇到未知错误,严重阻塞了Serverless架构在开发者侧的心智建设;
当然,上文所举例说明的几个方面也只是Serverless架构在配套资源、设施层面不完善的部分表现,除此之外,Serverless架构如何与传统框架有更紧密的结合;传统业务如何更容易迁移到Serverless;Serverless架构如何做监控告警;如何管理Serverless应用与Serverless资源;Serverless架构的科学发布、运维的最佳实践是什么样子的......问题也都是需要大家去思考和探索的。
时至今日,Serverless架构尽管还有很多的挑战需要面对,但是各个云厂商都在努力逃离当今的困境,希望通过更好的体验可以助力用户更简单、更快速的上Serverless架构,例如阿里云Serverless团队所开源的Serverless Devs项目,就是一款无厂商所定的,Serverless应用全生命周期管理工具。
如图所示,Serverless Devs 可参与到项目的创建、开发、调试、部署与运维的全流程中,以阿里云函数计算组件为例:
- 在项目的创建阶段,可通过命令行工具或者应用中心进行项目的最初创建;
- 在项目开发过程中,可以通过本地开发、调试等能力来验证本地开发的正确性;
- 在项目调试的环节,可以通过本地调试与远程调用、日志查询等能力,来进行项目的最终调试;
- 在部署环节,可以先通过依赖安装、项目构建等流程构建出完整的部署包,再进行项目的部署;
- 在后期运维环节,可以通过指标查询来进行项目健康度检查,通过日志查询等来进行问题定位,通过项目发布等能力进行版本发布,别名发布以及灰度发布等;
除此之外,各个云厂商也均在学习资源层面逐渐进行大力支持:
其他劣势
即使Serverless架构在如今已经非常热门,各个厂商也都在付诸更大的努力,完善自身的Serverless产品,推动Serverless生态和心智建设,但是Serverless架构在如今所暴露出的挑战,并不只有前文所描述的:
- Serverless架构在某些安全层面会有更大的挑战:尽管把更专业的事情交给了更专业的人,让Serverless架构在安全层面有了更大的保障,但是也由于Serverless架构的极致弹性能力让开发者们产生了更多的担心,“如果有人恶意对我的业务进行流量攻击,Serverless架构的极致弹性和按量付费会不会让我迅速产生巨大的损失?”,在国外就曾有创业公司因为遭受到恶意流量攻击,一夜之间Serverless架构让其损失数千美元,所以当安全性更高、性能更好的Serverless架构面对流量攻击时,所表现的结果是会产生巨大的费用支出,这与传统云主机所表现出的“无法提供服务的“是不同的,但是却更让开发者担忧。尽管现在很多厂商都在通过API网关的白名单与黑名单功能、函数计算的实例资源上限配置等相关功能对该问题进行求解,但是实际上仍然值得开发者们关注和深思;
- 出现错误难以感知也难以排查:由于Serverless架构相对传统云主机架构来说,更有一种”黑盒“的即视感,所以在Serverless架构下进行应用的开发,往往会出现一些难以感知的错误。例如某些经验不足的Serverless应用开发者在使用对象存储触发器时就可能会面临严重的循环触发问题,具体例子可以是,”客户端上传图片到对象存储,对象存储触发函数进行图片压缩操作,函数计算完成图片压缩操作之后,将结果图片回写到对象存储,如果这里的触发条件设置不清晰,就可能导致循环触发压缩、回写的操作“,在国外就有用户在使用S3触发AWS的Lambda时出现了循环回写和触发的情况,产生过数百美元的额外支出,直到账单报警才发现这个问题;当然,除了刚刚所描述的错误难以感知之外,Serverless架构往往还有错误难以排查的挑战,常见的情况是,当用户在本进行业务逻辑开发并调试完成,讲代码部署到线上就会出现偶现性错误,此时由于无法登陆机器进行调试,并且实例可能在触发之后会被释放,所以就出现了问题难以定位,问题难以溯源等挑战;
与Serverless架构的优势一样,即使我们在上文中已经举例说明了很多Serverless架构所面临的挑战,仍然没办法枚举出他在现阶段全部的劣势,虽然有一些挑战是已经有一些解决方案了,但是这些解决方案中往往也会因为用户需求过于强烈,存在一些违背Serverless所主张的精神的方案,例如:为了更好的解决冷启动问题,多家云厂商先后提出了实例预留功能,即当开发者无法信任Serverless平台可以更好的做弹性伸缩时,为了更大程度上降低冷启动带来的性能问题,云厂商允许开发者提前预留一些实例,以被需要。诚然,这种做法在一定程度上与Serverless所主张的精神有一定的冲突,却也是当前解决冷启动带来的性能损耗的一个比较有效的手段。
综上所述,不可否定的是随着时间的发展,Serverless架构所面临的挑战都会被广大群众所解决,甚至会因为这些挑战,将会为更多组织、团队带来新的机会。