前言Serverless演进云函数SCF开发NGWServerless同构直接解决方案前言Serverless最近又火了一把,很多业务都在云上实现了Serverless云函数,并取得了巨大的成功良好的落地效果,业界也在不断探索Serverless更多的落地场景。那么Serverless对于前端意味着什么呢?对于Node服务,serverless可以在哪里实现?答:无服务器同构和直出渲染。Serverless+SSR=?Serverless云函数:云计算发展过程中出现的对计算资源的抽象。它基于云计算平台,为开发者提供业务程序的运行环境。开发者无需关注底层资源分配和扩展。部署和代码执行所需的所有服务均由平台提供。SSR服务器端渲染:指在服务器端渲染HTML到前端。早期普遍采用phpjsp技术在服务器端生成HTML。近年来,在JS同构趋势的演变下,逐渐出现了在服务端运行前端JS代码进行渲染的解决方案,比如React、Vue等主流框架的同构渲染。Serverless技术若能应用到SSR场景,将具有以下优势:理论上可以无限扩展云服务资源,前端无需考虑业务量对SSR机器性能的影响;部署运维成本,提升开发效率目前,腾讯NOW直播IVWEB团队正在逐步将SSR业务迁移至腾讯云的云功能平台,以简化部署和运维成本。serverless的进化AJ是前端开发者。有一天,产品告诉他页面加载界面太长,体验很差。这对他作为一名优秀的前端开发人员来说并不难。他有99种方法可以让页面加载得更快。于是,他马上用团队直接导出框架,花了半天时间把页面连接到直接导出。接下来,他想将直接导出服务部署到现网。你申请多少核?业务量如何?有没有高并发场景?机器有扩容机制吗?如何更改Nginx配置以访问直接访问?正在一头雾水的时候,看到了腾讯云的同事maxlong关于serverless架构演进的PPT……从IaaS到FaaS在介绍云函数SCF之前,先来diff下传统IaaS业务架构和云函数FaaS业务架构:基于虚拟机的业务架构(IaaS)和云功能架构是这样的:基于云功能的业务架构(FaaS)阿J对比了两种架构,发现在基于云功能的业务架构下,开发者不再需要关注业务基础层的相关配置,可以关注业务逻辑的开发。平台负责维护和迭代基础层。只要我们的直连服务部署在云端,就可以解决直连服务部署中的运维痛点。FaaS+BaaS下ServerlessFaaS的出现使得服务上云变得更加容易,但是FaaS并没有解决“公共基础服务”的问题,所谓公共基础服务是基于对象存储、KV存储、消息推送。服务,这个问题最终还是落在了云服务提供商的身上。因此,市面上所有的云服务都无一例外地提供了上述“公共基础服务”。这种服务模式称为BaaS(BackendasaService)。Serverless直译为无服务器。这并不是说不需要服务器,而是开发者不需要关注服务器。该部分由平台维护提供。开发者只需要关注业务逻辑的开发。Serverless架构下的App在这样的架构下,开发者无需关注支撑应用服务运行的底层资源,以“函数”的形式承载业务逻辑,以“BaaS”的形式支撑公共服务服务”。Serverless在公有云基础设施上的演进考虑到直接服务的特点,阿J认为直接服务非常适合Serverless,于是马上开始了直接出云的预研,做ServelessSSR服务,免去运维和维护部署的烦恼,降低直接访问成本!SCF云函数开发者阿J仔细研究了腾讯云函数(ServerlessCloudFunction,SCF),发现它可以将我们的业务拆分成更细粒度的“函数”,而函数的执行环境开发者无需关注,并且平台负责。以下是阿J对云函数执行的理解。云函数执行过程在云平台上执行这些“云函数”的过程,其实就是对外提供服务。通常,serverless函数用于“响应HTTP请求”,即通过HTTP访问事件触发云函数的执行,如下图所示:云函数用户请求一个链接,“函数执行”不算什么四大要素:入参、上下文、返回值、副作用,如图:函数执行四大要素四大要素:“入参”:云函数的入参是请求头和请求体在HTTP请求中。“上下文”:包括函数请求的id、函数执行的环境变量等。“副作用”:云函数的执行可能会调用外部服务,如数据库、对象存储、数据监控等“返回”value":即HTTP响应如{retcode:0,msg:"ok"}AJ还了解到,按照一定的配置部署云函数后,云平台会给你一个URL,访问即可访问这个URL可以“触发”相应的云函数的执行并得到结果。NGWServerless同构直出方案就在阿J开始开发serverless直出的时候,突然发现serverless环境和原来的直出环境有很大的不同。原直出环境是这样的:原方案直接输出是使用TSW执行KoaApp,也就是说原方案需要监听端口,而不是作为函数运行。如何处理?老业务能否无缝迁移到云功能?它可以?使新的开箱即用的解决方案与旧的开箱即用的解决方案兼容?云函数如何设计、打包和发布,并连接到团队现有的CI流程?原来的方案可以在本地调试,但是云函数怎么在本地调试呢?云功能发布后,会得到一个URL,那么我们的业务域名下如何访问这个URL呢?工程打包去掉了前端的webpack打包,对于serverless云函数平台,我们要重新打包原来的打包产品。做一些操作,其核心是“打包为zip并上传到云函数”,如下图:云函数打包图标从图中可以看出,打包部署的过程是由“CLI工具”的目的是提供命令式部署原语,方便CI访问。serverless下的同构环境AJ考虑到原来业务直接输出的方案使用的是TSW,但是在serverless下,我们不能把TSW移到云函数中去执行,而是把我们需要的组件提取出来,比如ajax发送请求,监听和监控等常用组件reporting,loglogger,因为:方便老业务无缝迁移到云端功能,解决了直营业务的运维痛点。除了云函数的性能之外,还需要像这个TSW全局注入对象一样实现window.REQUEST插件,因为老方案也依赖这些全局对象。原来“流式”和“阻塞式”的解决方案需要Koa监听本地端口提供服务,而云函数的输入输出参数是块类型的,而Koa的输入输出参数是流类型的,所以这里我们需要处理云函数人参的输入输出参数。阿J的做法是根据云函数的入参动态构造http的IncomingMessage和ServerResponse的实例,然后透传给app.callback()进行直出渲染,最后从ServerResponse和将其构造为云函数的返回值。NGW用作网关转发。考虑到服务的可用性和之前链接接入的痛点,决定接入NGW(NodeGateway):NGW下的serverless直连可以通过NGW实现:实现底层逻辑:云函数是有可能崩溃的.这时候再去静态页面访问机的灰度逻辑:在直连上网的过程中,可以通过NGW的配置进行一些灰度测试。链接日志收集:一直以来,前端都不容易查看具体的链接信息,现在有了NGW,云函数在本地调试一切皆有可能。云函数的无状态模型使得本地调试变得非常容易。我们只需要输入本地构造函数的参数和上下文就可以直接直接调试了。AhJ在实际实现中,本地设置一个Koa服务监听端口,通过这个端口的请求构造入参和context,最后传入函数执行结果,返回给前端显示.同构直出流程到最后,阿J完成了serverless直出方案,直出流程如下图所示:下同构直出的三步“Init”新方案:初始化云函数环境,接受并处理云函数入口“Koa”:React同构业务逻辑以KoaApp的形式体现“清除”:清理云函数环境,处理KoaResponse并返回结果直接。有一点需要说明的是,Koa其实是对原有方案的封装,因此新方案在此基础上做了一些环境迁移和重写,使其可以在云函数环境中进行渲染。云函数的性能瓶颈和优化阿J在完成开箱即用的新方案后第一时间进行了压测,发现随着压测压力的增加,收包率会出现断崖式下降,他还发现有些功能的执行时间非常长。龙,我联系了一个云函数的同事,发现是“冷启动问题”,那么什么是冷启动呢?从云函数的架构可以看出,云函数被触发后并不是立即执行,需要一个环境初始化过程,这种启动称为冷启动;还有一种情况是请求的函数执行完后,马上就收到了下一个请求。此时无需重新初始化云函数环境,直接启动即可。这称为热启动。压测云函数执行时间分布图收包率优化前后(右边为优化后)冷启动问题在低压情况下不明显,但在高并发情况下会额外影响数据包返回。SCF同仁在此优化:增加最小实例数,减少冷启动。最小实例越多,可以支持的瞬时并发越多。优化效果如上图右侧所示。此外,我们还发现了内存问题。在这里,我们联系了SCF的同事,对Node内存模型进行了优化。优化后,4xx问题基本不存在。(也可以优化业务中的内存使用,避免JS内存泄露)内存溢出导致4xx问题。压力测试压力越大,错误越多。优化后的内存模型的性能已经达到了这个地步。阿J终于初步完成了Serverless。直出程序设计开发,并开始逐步在业务中使用和推广。
