本文将从前端的角度来看Serverless是什么,Serverless的出现会给前端带来什么样的机遇和挑战,并以一个具体的项目为例说明如何基于Serverless实现项目功能。
前端开发的横向演进
在刚开始的互联网时代,网页很简单,就是一些静态或简单动态的页面,主要是用来做信息的展示和传播。开发一个网页主要就是通过 JSP、PHP 等技术写一些动态模板。这个阶段还没有前后端的分工,通常是后端工程师顺便写了前端页面。
在 AJAX 技术出现之后,可以把 Web 分为前端和后端,前端负责界面和交互,后端负责业务逻辑的处理。前后端通过接口进行数据交互。随着页面越来越复杂,移动网络的应用的兴起,对加载性能有了更多的要求,通常异步渲染页面白屏时间比较长,另一方面对SEO也不够友好,所以落地页又回归到服务端渲染的这个方案。
前端在发展,后端也在发展,在分层和模块划分上更加的粒度化,微服务化。微服务的接口不再是面向页面,前端的接口调用变得复杂了,所以需要在微服务和前端中间,加了一个 BFF 层,全称(backend for frontend),由这一层 对接口进行聚合、裁剪后,再输出给前端。而这层不是后端本质工作,距离前端比较近,关系更大一些,所以前端工程师很自然选择了 Node.js 来实现。这也是当前 Node.js 在服务端比较广泛的应用。
可以看到,每一次前端开发模式的变化,都因为某个变革性技术的出现。先是 AJAX,然后是 Node.js。那么下一个变革性的技术是什么?不言而喻,就是 Serverless。
但是,如果完全让前端工程师来开发一个后端,需要考虑很多内容。
首先要考虑代码运行的环境和相关资源。比如前端代码运行的环境是用户的浏览器。后端环境需要服务器,网络,访问服务的域名、证书,服务器的操作系统,软件安装,webserver,数据库等。
除此之外,前端要考虑的是用户的网络,浏览器的兼容性,交互的流畅程度,还有视觉效果。后端还要考虑负载均衡,流量控制,弹性伸缩,高并发,备份容灾,安全防护,监控警告等。
前端并不擅长这些,但有了Serverless之后,这些我们基本上不用考虑,我们的主要精力可以用来实现业务逻辑。Serverless为什么能帮助做这些事情?
FaaS+BaaS可以称之为一个完整的Serverless,FaaS(Function as a Service) 是函数运行的平台。BaaS(Backend as a Service)则是一些后端云服务,比如云数据库、对象存储、消息队列等,通过使用BaaS,可以极大简化应用开发难度。开发者将代码上传到云函数平台,并配置相关的触发器。平台根据触发器事件,完成运行环境的准备、调度、执行和扩容这些工作。
从架构上,可以看到Serverless 的这些特点:
无运维,使用 Serverless 我们不需要关心服务器,不需要关心运维,这也是 Serverless 思想的核心。
无状态,因为每次函数执行,可能使用的都是不同的容器,无法进行内存或数据共享。如果要共享数据,则只能通过Redis 、COS等第三方服务。
事件驱动,函数在 FaaS 平台中,是需要通过事件来触发函数执行。
低成本,实现按需调用,按需伸缩、按使用收费。
基于Serverless的前端开发模式
01
BFF
基于Serverless,前端的一些通用开发模式可以怎么来做呢?下图是比较通用的BFF架构。最底层是后端微服务,最上层是前端应用,在微服务和应用之间,是通常由前端工程师开发的 BFF层,对接口进行聚合裁剪,在返回给前端使用 。
这样的架构解决了接口协调的问题,但也带来了一些新的问题。以前前端只需要关注浏览器端的渲染,现在却需要维护各种 BFF 应用以及运维,但是通常前端并不擅长运维。Serverless的出现可以很好的解决这些问题。基于 Serverless,可以使用云函数来实现BFF层,只需要关注业务逻辑,运维的工作交给了Serverless平台。
图中的APIGateway代替了我们的nginx代理服务器,以前可能是将转发规则写在代理服务器的配置文件中,现在在API网关中有了可视化的管理、可监控、可设置版本等等更多更易用的功能。
02
SSR
传统的服务端渲染,服务端根据路由返回渲染好的HTML页面。而在Serverless上实现也类似,可以将多个页面返回放到一个函数中,也可以将每个页面拆分成一个个云函数,这样用户请求的一个页面,对应的就是每个单独的函数。
03
小程序
目前国内使用 Serverless 较多的场景可能就是小程序开发了。在传统的小程序开发中,需要前端工程师进行小程序端的开发;后端工程师进行服务端的开发。小程序的后端开发和其他的后端应用开发,本质是是一样的,需要关心应用的负载均衡、弹性伸缩,备份冗灾、监控报警等等运维操作。
但基于云开发,开发者只需要关注于业务的实现,由一个前端工程师就能够完成整个应用的前后端开发。应用的运维转移到了云平台上。
04
后端思维
前端工程师去基于Serverless去写后端,最好也要具备一定的后端知识。涉及复杂的后端或者Serverless不适用的场景,还是需要后端去开发,只不过后端变得更加靠后。简单说说前后端开发异同之处。
1、共性思维,就是前端后端都通用的。
第一个工程化,分层模式,前端的工程化现在也相当的成熟,视图和数据分离,组件和页面的组装,而后端最基本的一个分层模式就是DAO层,业务模块层,接口层。
可用性:监控一切。这个大家都比较好理解,服务端监控包括:接口,各种服务,机器的性能等等
高性能:和前端有各种缓存技术方案一样,在后端如果要提升性能,一样需要利用缓存,理论上每个层级都可以缓存,从数据库到Redis,内存,从元数据到渲染好的页面,但缓存越多,系统复杂度也越高,需要根据需求成本来平衡方案取舍。
2、安全意识。
防别人对付用户 :设置 CSRF Token
防用户对付系统:参数校验、权限检查、防SQL注入
防系统对付自己:提交防重/频率控制
3、并发意识。服务端和前端主要不同的点是,服务端同时服务所有用户,需要有并发的意识。
资源多级隔离:防止一个有问题导致系统雪崩。
共享数据加锁:比如有限数量的商品多人同时下单的场景。
任务队列缓存:将高并发放到任务队列中,减缓并发高峰,让高并发变得更为可控一些。
如何基于Serverless进行项目开发
程序受众广易传播,开发成本低,效果好等特点,非常适合老产品拉新/创新,新产品快速尝试。这里以一个背单词小程序为例。
01
项目需求
这个项目的核心需求是学习单词,记录学习情况,学习单词又包含看单词,听单词发音,读单词,系统对用户发音进行评分,还有检验。
基于Serverless的技术方案如下,可以看到有登陆模块,通过云函数,调用微信的API进行登录校验。语音合成和口语评测这两个功能,腾讯云就有这两个服务,可以直接调用,需要做的仅仅是通过云函数进行鉴权中转。学习记录这部分,就结合函数逻辑和云数据库来完成。可以看到项目的完整层级架构,是非常清晰简单的。
一个项目的完整开发流程包括设计/开发、调试、测试、上线、监控/运维,下面展开说一下基于Severless每个阶段具体是怎样做的。
02
设计/开发
以下是一个基于serverless的web应用通用架构。
主要有三部分:
静态资源存放
静态资源(JS/CSS/IMG/HTML)放在COS(对象存储),COS可以自定义域名和开启CDN加速,通过URL直接访问。
模板文件和数据文件放在COS,函数通过COS SDK可以很方便的对文件进行读写。
数据存储使用
由于Serverless的特点是事件触发,用完释放。那么需要考虑本地存储和缓存必须依赖于第三方服务如COS(对象存储)和Redis。不过函数实例本身会有延迟释放的时间,便于在新请求来的时候可以复用,可以利用本地缓存作为第一级缓存。
DB/Redis的连接访问和原来一样,在云平台申请相关存储资源,设置和云函数相同的虚拟子网,云函数就可以通过内网地址进行资源访问,保证了数据服务和外网的安全隔离。腾讯云数据库提供了全套运维解决方案,大大简化了运维工作。
应用逻辑实现
传统架构上请求是由Nginx代理转发到相关nodeserver上去处理,而Serverless是请求到了API网关再转发到云函数上处理。原来的转发内容是HTTP请求,云函数上接收的是API网关事件。为了应对这种变化,可以在代码中直接去解析使用API 网关事件。但如果已经很习惯express的开发框架,而且很依赖一些好用的中间件,如果需要重建这部分中间件,这会是不小工作量。
那有没有方案兼容原来的写法?可以将API网关事件转换成http请求,通过本地socket和函数起nodeserver进行通信。
但这样中间经过了一层的转发,性能会不会有所损耗呢?在耗时统计来看,有了这一层转发,云函数平均耗时也在20ms之内,中间即使有性能损耗也在毫秒级别的了,相对于网络耗时来说,就是小巫见大巫了。
所以非必要的情况下,无论是迁移还是新开发的web项目其实都可以采用这个方案:
中间转发代理层已经有一些可用的框架(serverlessplus, scf-framework)。
03
调试
接下来看一下怎么调试云函数。
第一种,通过命令行可以很方便的将代码发布到云函数平台上,支持云上调试
第二种,对于复杂一点的应用,可以使用SCF命令行工具在本地环境进行调试。
第三种,我们前端可能比较习惯在浏览器中直接刷url来调试,如果项目是基于koa或者express之类的框架,可以直接增加一个server的入口,调试的时候就直接本地起一个nodeserver来调试。
但是目前发布到云函数是要包含node_modules文件夹的,压缩之后,需要通过网络传输上去。如果改一行代码,就要上传一次来执行,这样比较复杂,而且在线的IDE也是只能编辑入口文件的,但是代码都不是写在入口文件那的,升级IDE需求也在规划开发中。
如果在本地调试,需要提前安装SCF CLI命令行工具、docker,这个运行方式的原理是,加载一个和云函数环境相同的一个镜像,然后在docker中去执行。然而还是会遇到一些问题:
比如连接的数据库需要是外网地址,因为docker的网络环境和本地并不能连通,与云上的环境也不能连通。
还有,比如我在本地安装的npm包,也不能正常执行,因为本地开发环境是mac系统,而镜像是linux系统。
SCF CLI本地命令行工具,可以支持native调试,就是用本地的环境进行调试。这样就解决了数据库连通问题,以及调试时操作系统差异问题。(那么系统差异的问题只能是需要一个专门的编译机了,一般情况下,如果依赖的npm库如果不涉及到操作系统差异的话,npm包都是可以通用的。)
如果项目是基于koa或者express之类的框架,可以直接增加一个server的入口,调试的时候就直接本地起一个server,和普通node server一样的进行调试。
04
测试/上线/迭代
前面说到用命令行工具很方便的将代码发布到云函数平台上。还需要测试、上线与回滚。云函数本身有发版本功能。API网关也默认有测试、预发布、发布3个环境,每个环境可以指定云函数的版本。这样看起来就可以将测试和线上的环境区分开。
但是,测试和线上连接的资源是不一样的,比如DB,我们通常是通过读取环境变量来判断是测试环境还是线上环境,但是一个云函数只有一个配置。
腾讯云函数还提供了命名空间、函数复制这样的功能。利用这些功能可以:
测试和线上放在两个不同到命名空间,隔离测试和线上代码,更加安全;
测试和线上环境通过函数配置不同的环境变量来区分;
上线通过复制函数来完成,选择不复制配置;
回滚通过API网关切换函数版本来完成。
这样就可以满足我们的测试部署、上线部署,回滚的需求了。
05
运维/告警/监控
在serverless下,运维需要做哪些呢?负载均衡,流量控制,扩缩容,高并发,安全防护这些都由云函数平台做了。另外云函数接入了云监控,在云监控我们可以自定义统计视图,配置告警阈值和告警方式,还可以上报自定义的监控点。
至此,从开发到调试,从部署到运维,一个项目的完整开发流程都已经完成了。
最后,谈一下对云函数的展望,现在使用HTTP协议时,需要通过API GATEWAY中转一层,能不能去掉这一层中转?如果业务应用比较复杂,需要拆成多个云函数来承载,对于这样的现有项目能否0改造迁移?现在部署云函数的时候,需要将lib库也打包上传,未来希望能和代码仓库打通,在git push的时候,能够在线编译,并且自动部署。
开发者所想,也是服务商所想,这些功能腾讯云都正在开发中,近期将会发布,敬请期待!
关联阅读:前端学Serverless系列--性能调优
活动推荐
从开源OpenResty高性能解密、API 网关背后的技术难点分析到企业如何利用云环境快速上线服务、个人开发者如何轻松创业……API 网关能给你的生活带来哪些改变?7月13日,4位API网关专家将带你从多个方面深入理解API网关。感兴趣的读者赶紧点击阅读原文报名啦~