当前位置: 首页 > 科技观察

利益还是挑战?Serverless到底给前端带来了什么

时间:2023-03-14 11:55:09 科技观察

介绍Serverless是一种“无服务器架构”,可以让用户专注于业务逻辑,而不必关心程序的运行环境、资源和数量。既然公司已经实现了DevOps,正在向Serverless迈进,那么前端为什么还要关注Serverless呢?针对业务前端同学:会改变前后端接口定义规范;肯定会改变前后端联调方式,让前端参与服务端逻辑开发,甚至NodeJava混合;大大降低了Nodejs服务器的维护门槛,只要会写JS代码就可以维护Node服务,无需学习DevOps相关知识。对于一个自由开发者:未来服务器部署会更加灵活,性价比更高;部署将更快,更不容易出错。前端框架总是带来后端的思维,而Serverless则是将前端的思维带入后端运维。前端开发者其实是最先享受到“Serverless”好处的群体。他们不需要有自己的服务,甚至不需要有自己的浏览器,这样他们自己的JS代码就可以在每个用户的电脑上均匀、负载均衡地运行。而每个用户的浏览器,就像最时尚成熟的Serverless集群一样,从远程加载JS代码开始冷启动,甚至引领冷启动:利用JIT加速让代码实现毫秒级冷启动。不仅如此,浏览器还为BaaS服务实现了完善的环境。我们可以调用任意一个函数来获取用户的cookie、环境信息、本地数据库服务,而不用关心用户使用的是什么电脑,连接的是什么网络,甚至是硬盘。尺寸。这就是Serverless的思想。通过FaaS(FunctionasaService)和BaaS(BackgroundasaService),试图在服务端打造一个前端开发者习惯的开发环境,让前端开发者能够更好的理解无服务器的好处。精读FaaS(FunctionasaService)+BaaS(BackgroundasaService),才称得上是一个完整的Serverless实现。除此之外,还有PaaS(PlatformasaService)的概念。通常,平台环境都是通过容器技术实现的,最终是要实现NoOps(无人运维),或者至少是DevOps(开发&运维)。简单介绍一下这几个名词,防止大家混淆:FaaS-FunctionasaserviceFunctionasaservice,每个函数都是一个服务,函数可以用任何语言编写,无需关心任何运维细节,如:计算资源,弹性扩展,可按量计费,支持事件驱动。业界所有主要的云供应商都支持FaaS,并且每个供应商都有一套工作台或可视化工作流来管理这些功能。BaaS-Backendasaservice后端和服务,就是集成了很多中间件技术,可以不受环境调用服务,比如Dataasaservice(数据库服务),缓存服务等。下面虽然有很多XAAS,但仅FaaS+BaaS构成了Serverless的概念。PaaS-Platformasaservice平台即服务,用户只要上传源代码,就可以自动持续集成,享受高可用服务。如果速度够快的话,可以考虑类似于Serverless。但随着以Docker为代表的容器技术的兴起,基于容器的PaaS部署逐渐成为主流,是最常用的应用部署方式。如中间件、数据库、操作系统等。DaaS-Dataasaservice数据即服务,将数据收集、治理、聚合,服务打包提供。DaaS服务可以应用Serverless架构。IaaS-InfrastructureasaServiceInfrastructureasaService,例如计算机存储、网络、服务器和其他基础设施作为服务提供。SaaS-SoftwareasaService软件即服务,如ERP、CRM、电子邮件服务等,以软件的粒度提供服务。容器容器是隔离物理环境的虚拟程序执行环境,环境是可以描述和迁移的。比较流行的容器技术是Docker。随着容器数量的增加,管理容器集群的技术应运而生。众所周知的容器编排平台是Kubernetes。容器技术是一种选择,也是实现Serverless架构的基础。NoOps是无人运维,比较理想化。或许可以借助AI能力,实现完全无人化运维。无人运维不等于Serverless。Serverless可能也需要人为运维(至少目前是这样),但开发者不再需要关心环境。DevOps的作者认为可以理解为“开发就是运维”。毕竟出了问题,开发是要承担责任的,而成熟的DevOps体系可以让更多的开发者承担起OP的责任,或者与OP更紧密的合作。回到Serverless,以后后端开发的体验可能和前端差不多:不用关心代码运行在哪个服务器(浏览器)上,不用关心服务器环境(浏览器版本),不用担心负载均衡(前端从来不用担心),可以随时调用中间件服务(LocalStorage,ServiceWorker)。前端同学应该对Serverless特别感兴趣。以笔者的亲身经历为例。说起做游戏,笔者对开发游戏十分痴迷。最常见的养成类游戏就是资源建设、收集,或者挂机时计算资源的倒计时规则。笔者在开发游戏时,一开始将客户端代码和服务端代码完全分为两套实现://...UI部分,绘制一个倒计时的记录员营地建设进度条constcurrentTime=awaitrequestBuildingProcess();constleftTime=newDate().getTime()-currentTime;//...继续倒计时阅读文章//阅读文章后,每小时木头产量+100,更新到客户端timerstore。woodIncrement+=100;游戏体验方面,用户可以在不刷新浏览器的情况下,看到伐木场建造进度的阅读栏,“轰”的一声建造完成,发现自己每秒多了100个木头!但是当lumberyard的搭建完成后,完成后随时刷新浏览器,逻辑要维护,数据需要在后端离线计算。此时,需要编写后端代码://每次登录时,验证当前登录constcurrentTime=newDate().getTime()//获取日志农场的当前状态if(/*underconstruction*/){//return给客户端当前时间constleftTime=building.startTime-currentTimeres.body=leftTime}else{//建设完成store.woodIncrement+=100}很快,建筑类型就多了,不同的状态,不同层次的输出,前后端分开维护的成本会增加,我们需要做配置同步。配置同步为了实现前后端配置的同步,可以将配置分开托管,实现前后端共享。例如新建一个配置文件来存储游戏信息:exportconstbuildings={wood:{name:"..",maxLevel:100,increamentPerLevel:50,initIncreament:100}/*..andsoon..*/};虽然复用了配置,但是前后端有一些共同的逻辑可以复用,比如根据建筑建造时间判断建筑状态,N秒输出后判断建筑等,Serverless带来了进一步优化的空间.想象一下在无服务器环境中玩游戏。您可以以函数粒度在服务器上执行代码。我们可以这样抽象游戏逻辑://根据建筑建造时间判断建筑状态exportconstgetBuildingStatusByTime=(instanceId:number,time:number)=>{/**/};//判断建筑生产exportconstgetBuildingProduction=(instanceId:number,lastTime:number)=>{conststatus=getBuildingStatusByTime(instanceId,newDate().getTime());switch(status){case"building":return0;case"finished"://accordingto(currenttime-lastopentime)*outputpersecond得到总输出返回;/**/}};//前端UI层每秒调用getBuildingProduction函数,及时更新生产数据//前端入口函数exportconstfrontendMain=()=>{/**/};//后端根据每次开盘时间调用一次getBuildingProduction函数并入库//后端入口函数exportconstbackendMain=()=>{/**/;使用PaaS服务,将前后端逻辑写在一起,将getBuildingProduction函数片段上传到FaaS服务,实现前后端逻辑同时共享!在文件夹视图中,可以进行如下结构规划:.├──client#前端入口├──server#后端入口├──common#共享工具功能,可以包含一般游戏的80%逻辑。可能有人会问:前后端共享代码只能用Serverless来做。确实,如果代码抽象的足够好,并且有成熟的工程方案支持,是可以将一段代码分别导出到浏览器和服务端的。而基于函数粒度的Serverless更符合前后端代码复用的理念。它的出现可能会促进更广泛的前端和后端代码重用。这虽然不是什么新发明,但也足以称得上是天翻地覆的变化了。前后端视角对于前端开发者来说,他们会发现后端服务变得更简单了;对于后端开发人员来说,他们会发现服务更厚,面临的挑战也更多。更简单的后台服务租用传统ECS服务器时,CentOS和AliyunOS的环境选择就足以惹麻烦了。对于个人开发者来说,我们很难搭建一个完整的持续集成服务,而且选择很多,让人眼花缭乱:可以在服务器上安装数据库等服务,在本地直接用服务器的数据库进行开发;安装Docker连接本地数据库服务,将环境打包成镜像,整体部署到服务器;前后端代码分离,在本地开发前端代码,在服务器端开发服务端代码。甚至服务器的稳定性也需要PM2等工具进行管理。当服务器面临攻击、重启、磁盘故障时,只能通过打开复杂的工作台或登录Shell来恢复。这如何使人们专注于做什么?Serverless解决了这个问题,因为我们要上传的只是一段代码,不再需要面对服务器、系统环境、资源等环境问题,对外服务也有PackagedBaaS系统支持。其实在Serverless出来之前,很多后端团队都是通过FaaS的概念来简化开发流程的。为了减少编写后端业务逻辑时环境和部署问题的干扰,很多团队会将业务逻辑抽象成块(Blocks),对应代码片段或Blockly。这些块可以独立维护和释放,最后将这些代码片段注入到主程序中,或者动态加载。如果习惯了这种开发方式,就更容易接受Serverless。更厚的后台服务站在后台,事情就变得更复杂了。与提供简单的服务器和容器相比,现在需要对用户屏蔽执行环境,让服务变得更厚。笔者通过一些文章了解到,Serverless的实现还面临以下挑战:各厂商的Serverless实现种类繁多,如果业务要部署在多云中,需要磨平差异;成熟的PaaS服务其实都是伪Serverless的,未来如何标准化;FaaS冷启动需要重新加载代码和动态分配资源,导致冷启动非常慢。除了预热之外,还需要一种经济的优化方法;对于高并发(比如双11闪购)场景的应用,不需要容量评估是很危险的,但是如果能够完全弹性,就省去了麻烦的容量评估;如何迁移库存应用程序。业界大多数Serverless服务商都没有解决现有应用迁移的问题;Serverless的特性导致无状态,而复杂的互联网应用是有状态的,所以在不改变开发习惯的情况下支持状态是一个挑战。幸运的是,这些问题已经在积极处理中,其中许多问题已经有了解决方案。Serverless给后台带来的好处远不止它面临的挑战:促进前后端融合。进一步降低Node编写服务端代码的门槛,避免应用运行的学习成本。笔者曾经遇到过我申请的数据库服务被迁移到其他机房导致的应用服务中断。我不用再担心了,因为数据库是一个BaaS服务,所以我不需要关心它部署在哪里,是否跨机房,如何迁移;提高资源利用效率。杜绝应用独占资源,转为按需加载,肯定会减少不必要的资源消耗,将服务均匀分散到集群中的每台机器上,拉平集群的CPU水平;降低云平台使用门槛。无需运维,弹性扩展,价值服务,高可用。这些能力在吸引更多客户的同时,完全按需计费的特性也减少了用户开支,实现了双赢。使用Serverless尝试打通服务。笔者在公司负责一个大型BI分析平台的建设。BI分析平台的底层能力之一就是可视化构建。那么如何打通可视化构建能力呢?现在可以更轻松地打开组件。毕竟前端可以和后端设计相对解耦,AMD加载系统也比较成熟。现在遇到的挑战之一就是后端能力的开放性,因为当接入能力有自定义需求时,可能需要自定义后端数据处理的逻辑。目前能做的就是使用maven3和jdk7搭建本地开发环境测试。想要上线,需要后端同学的协助。如果后端构建了一个独特的ServerlessBaaS服务,就可以像前端组件一样进行在线编码、调试,甚至灰度发布进行预发布测试。现在前端云开发已经有很多成熟的探索。Serverless可以在不关心环境的情况下统一云端前后端代码开发的体验。Serverless应用架构设计看了一些Serverless应用架构图,发现大部分业务都可以应用这样的架构图:业务功能抽象为FaaS功能,数据库、缓存、加速等服务抽象为BaaS服务;上层提供Restful或事件触发机制调用对应不同终端(PC、移动端);扩展平台能力,只需要在终端开放(组件接入)和FaaS服务(后端接入)即可。好处与挑战Serverless带来的好处与挑战并存。本文从前端的角度讲一下。好处一:前端更专注于前端的体验技术,不需要过多的应用管理知识。最近看了很多资深前端前辈写的总结文章,最大的体会就是回忆“前端这几年起到了什么样的作用”。我们倾向于夸大自己的存在感。其实前端存在的意义就是解决人机交互的问题。在大多数场景下,它是锦上添花,而不是必须的。回想自己最得意的工作经历,可能是掌握Node应用运维知识、前端工程系统搭建、研发效率优化、标准规范制定等,但真正为业务工作的部分恰恰是你认为写得最少的部分。业务代码也罢。前端在外围技术上花的时间太多,减少了很多对业务和交互的思考。即便是大公司,也很难招到精通Nodejs、运维知识丰富的人。同时,要求他有精湛的前端技术和对业务的深刻理解。鱼和熊掌几乎不可能兼得。Serverless可以有效解决这个问题。前端同学只需要会写JS代码,不需要掌握任何运维知识,就可以快速实现自己的一套想法。确实需要了解服务器端的知识,但是从合理分工的角度来说,前端应该侧重于前端技术。前端的核心竞争力或者说它带来的商业价值,是不会靠更多的运维知识来补充的。相反,它会吞噬掉我们本可以带来更多商业价值的时间。语言、浏览器、服务器的演进是一个从复杂到简单,从底层到封装的过程,而Serverless是后端+运维整体进一步封装的过程。好处二:逻辑编排带来的高复用和可维护的代码,可以扩展云+端的能力。云+客户端是前端开发的下一个形态,提供强大的云编码能力,或者通过插件将客户端构建成类云的开发环境。它最大的优点是屏蔽了前端开发环境的细节。这个概念类似于Serverless。很多团队都尝试过使用GraphQL让界面“更有弹性”,而Serverless是更彻底的解决方案。我自己的团队尝试过GraphQL的方案,但是由于业务的复杂性,很难用一个标准的模型来描述所有场景的需求,所以不适合使用GraphQL。正是基于区块链的可视化后端开发平台坚持了下来,并取得了惊人的开发效率。这套Blockly的广义抽象几乎可以被Serverless取代。因此,Serverless可以解决复杂场景下后端研发效率提升的问题。Serverless集成云开发后,可以通过逻辑排列进一步可视化调整函数执行顺序和依赖关系。笔者之前在百度广告数据处理团队使用过该平台计算过离线日志。每个MapReduce计算节点可视化后,很容易看出故障时是哪个节点阻塞了,最长的执行链路可以看出来,并为每个节点重新分配执行权重。即便逻辑编排不能解决所有的开发痛点,但在特定的业务场景下肯定能有所作为。挑战一:Serverless能否彻底取消前端转后端的门槛?前端同学写Node代码最常见的问题就是内存溢出。Browser+Tab自然是近距离使用的场景,UI组件和逻辑的创建和销毁非常频繁,所以前端同学很少,几乎不需要关心GC问题。但是GC在后端开发场景中是一个由来已久的习惯,所以Nodejs程序的缓冲区溢出是大家最关心的问题。Serverless应用程序是动态加载的,如果长时间不使用就会被释放。所以,一般来说,不用太担心GC。即使内存溢出,进程也可能在内存满之前就已经释放了,也可能检测到异常时被强行kill掉。.但毕竟FaaS函数的加载和发布完全由云端控制,一个常用的函数有可能很长时间都不会卸载,所以FaaS函数还是要注意控制副作用。所以,Serverless虽然把运维环境打通了,但是服务器的基础知识还是需要了解的。你必须清楚代码是运行在前端还是后端。挑战二:性能问题Serverless的冷启动会导致性能问题。让业务方主动去关心程序的执行频率或者性能需求,然后开启预热服务,这又会把研发拖入运维的深渊。在业务根本不关心调用频率的情况下,即使是业界最成熟的AmazonServerless云服务也无法轻松应对闪杀场景。因此,目前来看,Serverless可能更适合在合适的场景下使用,而不是强行要求任何应用去应用Serverless。虽然可以通过定时运行FaaS服务来保证程序一直在线,但是笔者认为这还是违背了serverless的理念。挑战三:如何保证代码的可移植性有一张经典的Serverless定位描述图:网络、存储、服务、虚拟家园、操作系统、中间件、运行时、数据不需要关心,甚至应用层只需要你关心功能部分,而不关心启动和销毁等其他部分。这在过去总是被视为优势,但反过来也可以被认为是劣势。当你的代码完全依赖于一个公有云环境时,你就失去了对整体环境的控制,甚至代码只能运行在特定的云平台上。不同的云平台提供的BaaS服务规范可能不同,FaaS的入口和执行方式也可能不同。如果要采用多云部署,就必须克服这个问题。现在很多serverless平台都在考虑标准化,但同时也有一些自下而上的工具库来抹平一些差异,比如ServerlessFramework等。我们在写FaaS函数的时候,也尽量把平台绑定的入口函数写的轻一点,真正的入口放在main等通用函数中。综上所述,Serverless的价值远大于挑战,其理念可以有效解决很多研发效率问题。但是目前serverless的发展阶段还处于早期阶段,国内的serverless也处于试用阶段,在执行环境上还有很多局限性,就是serverless的美好理念还没有完全实现,所以如果一切定了,肯定会被踩。可能3-5年后,这些坑就会被填平,那么你是选择加入填坑大军,还是选择合适的场景使用Serverless?