Serverless从入门到放弃 | 4. Serverless网站开发实践

676 阅读6分钟

本文介绍使用Serverless搭建网站实践,包括技术栈、优化和最终为什么放弃。

第一阶段 一体化

灵题库(www.lingtiku) 是一个前端题库网站,包括用户端和管理后台。

一开始采用了前后端一体化的方案,部署在FaaS。

使用在阿里云申请的免费证书支持https。

FaaS使用阿里云的函数计算,使用Midway Serverless框架的React模板,用mysql库连接数据库,orm使用typeorm,使用nodemailer发送邮件实现注册功能,joi进行接口参数校验。

前端方面,该模板使用vite进行打包,灵题库使用redux管理状态 + react-router实现路由能力,组件库用antd,css预编译用stylus,富文本用quill。

由于Midway框架丰富完善的功能,第一版很快就上线了。

第二阶段 前后端分离

但是马上出现了性能问题。白屏时间太长,经过排查,大概猜测到了原因,因为购买的是FC的按量模式,这个在之前文章中有介绍,当没有请求时候,没有实例在工作,当开始有请求时候才会启动实例来响应,实例可以复用,所以多个请求在一段时间内可能响应很快,但是长时间没有请求,突然一个请求过来,会有初始化时间的延时。

而且,前端代码不断迭代,代码、图片、字体等不断增加,整个项目体积会不断增长,白屏时间也会越来越长。另外阿里云的FC规定如果体积超过50M需要提供oss的地址以存放代码。

总结一下就是

  1. 如果使用按量模式,白屏会比较严重,如果使用预留模式,则要支付额外费用

  2. 前端项目体积在迭代过程中增长较快,会导致超过50M限制,FC要求提供oss以存放代码。

基于以上问题,经过权衡,网站放弃了一体化方案,将前后端分离,前端项目部署到ecs上,后端api继续使用FC。

第三阶段 优化

分离之后白屏问题消失了,前端页面很快展示。但是API依然存在首次启动慢的问题,导致首次访问时候,数据加载中的loading时间较长,这也是让用户难以接受的体验。

为了解决首屏内容加载慢,采用了前端预渲染的方案。

前端预渲染

但前端预渲染只能解决首屏加载慢,从首屏继续访问其他页面、从其他页面退回首屏,都可能因为FC首次启动慢而导致需要用户长时间等待的情况。

因此又采取了数据预下载的优化方案。

数据预下载

预渲染和数据预下载不能保证每次成功,因为本地请求接口时间也不固定,即使设置为60s,也还是存在FC接口没有几十响应的情况,因此每次本地构建完,都需要手动检查一下(如果自动化检查,当项目更新,也还要更新检查脚本),这让项目变得不好维护。

每次后台数据更新,都要重新构建,以保证首屏渲染数据是最新的。

前后端拆分还要注意一个问题是跨域访问问题

本地支持跨域cookie设置和访问,需要服务器设置header:access-allow-control-credentials为"true",并设置access-allow-control-origin为指定的origin,前端xhr.withCredentials设置为true。另外前端需要通过ip访问,请求后端接口也需要通过ip访问。注意有些浏览器(如chrome)默认设置cookie的samesite为"lax",且拒绝接受不为secure的samesite为"none"的cookie,sucure必须设置为“true”,即https访问。

本地调试,如果前端项目和后端项目都用ip访问,即使端口不同也不会导致跨域,因此我们通过ip访问本地项目就可以前后端调试了。

最后 放弃

注意到这时候系统已经渐渐变得复杂起来。

除了项目更加复杂,FC还有一个让人头疼的特性:IP不固定,这个很好理解,因为实例都是动态管理的,IP不固定的话对于Serverless平台更好管理。这个特性导致API放在FC时候,在和其他开放平台交互的场景(如微信公众后台)需要特殊处理,如果API server需要调用微信的接口,必须在微信公众平台配置服务器的IP白名单,但是FC实例IP不固定,没有办法配置白名单,对于这种情况,FC给出的建议是,通过一个拥有固定IP代理服务器发送请求,这就增加了系统的复杂度,而且还需要额外购买服务器。

还有一个问题,由于使用FC实现API,实例是并发的、动态的,对于在内存中保存多个接口共享的数据的场景(虽然这样做不推荐),FC就无能为力了,在灵题库网站中,为了实现验证码登录,只好采用了token的方式。没有redis,不能用内存,如何实现一个验证码登录功能?

因为存在这些问题,对于灵题库这个轻量的、资金投入受限的网站,后续还是想把API从FC上迁出来,用Go重构到ECS上面。

总结

下面总结下使用Serverless搭建网站大半年的个人的感受,在web开发场景说说Serverless对于前端的机会。

FaaS是后端服务运行环境,简化后端运维,但对于小型的应用,不用考虑并发,其运维成本和ESC差不多,而且在一些场景还更麻烦(如它没有固定ip,不能在内存中存储状态)。只适合有一定规模的大型应用的使用。而Serverless普及程度不高,目前没听说有公司全站上Serverless的,因此前端想通过Serverless转全栈还是不太现实。

BaaS可以绕过后端服务,可以开发一款独立应用,因此对于前端想开发独立产品,可以选择BaaS产品,还省去了联调,提高开发效率。但同样普及度不高,因此在提高职场竞争力方面还是没什么空间。

结论:对于纯前端(没有太多后端运维经验),可以学习Serverless作为技术储备,但不建议作为提高核心竞争力的方向。