Serverless從入門到放棄 | 4. 網(wǎng)站開發(fā)實(shí)踐
時(shí)間:2023-05-25 07:24:01 | 來(lái)源:網(wǎng)站運(yùn)營(yíng)
時(shí)間:2023-05-25 07:24:01 來(lái)源:網(wǎng)站運(yùn)營(yíng)
Serverless從入門到放棄 | 4. 網(wǎng)站開發(fā)實(shí)踐:前面幾篇文章介紹了Serverless的基本概念、開發(fā)平臺(tái)和框架。
本文介紹使用Serverless搭建網(wǎng)站實(shí)踐,包括技術(shù)棧、優(yōu)化和最終為什么放棄。
第一階段 一體化
靈題庫(kù)是一個(gè)前端題庫(kù)網(wǎng)站,包括用戶端和管理后臺(tái)。
一開始采用了前后端一體化的方案,部署在FaaS。
使用在阿里云申請(qǐng)的免費(fèi)證書支持https。
FaaS使用阿里云的函數(shù)計(jì)算,使用Midway Serverless框架的React模板,用mysql庫(kù)連接數(shù)據(jù)庫(kù),orm使用typeorm,使用nodemailer發(fā)送郵件實(shí)現(xiàn)注冊(cè)功能,joi進(jìn)行接口參數(shù)校驗(yàn)。
前端方面,該模板使用vite進(jìn)行打包,靈題庫(kù)使用redux管理狀態(tài) + react-router實(shí)現(xiàn)路由能力,組件庫(kù)用antd,css預(yù)編譯用stylus,富文本用quill。
由于Midway框架豐富完善的功能,第一版很快就上線了。
第二階段 前后端分離
但是馬上出現(xiàn)了性能問(wèn)題。白屏?xí)r間太長(zhǎng),經(jīng)過(guò)排查,大概猜測(cè)到了原因,因?yàn)橘?gòu)買的是FC的按量模式,這個(gè)在之前文章中有介紹,當(dāng)沒(méi)有請(qǐng)求時(shí)候,沒(méi)有實(shí)例在工作,當(dāng)開始有請(qǐng)求時(shí)候才會(huì)啟動(dòng)實(shí)例來(lái)響應(yīng),實(shí)例可以復(fù)用,所以多個(gè)請(qǐng)求在一段時(shí)間內(nèi)可能響應(yīng)很快,但是長(zhǎng)時(shí)間沒(méi)有請(qǐng)求,突然一個(gè)請(qǐng)求過(guò)來(lái),會(huì)有初始化時(shí)間的延時(shí)。
而且,前端代碼不斷迭代,代碼、圖片、字體等不斷增加,整個(gè)項(xiàng)目體積會(huì)不斷增長(zhǎng),白屏?xí)r間也會(huì)越來(lái)越長(zhǎng)。另外阿里云的FC規(guī)定如果體積超過(guò)50M需要提供oss的地址以存放代碼。
總結(jié)一下就是
1. 如果使用按量模式,白屏?xí)容^嚴(yán)重,如果使用預(yù)留模式,則要支付額外費(fèi)用
2. 前端項(xiàng)目體積在迭代過(guò)程中增長(zhǎng)較快,會(huì)導(dǎo)致超過(guò)50M限制,F(xiàn)C要求提供oss以存放代碼。
基于以上問(wèn)題,經(jīng)過(guò)權(quán)衡,網(wǎng)站放棄了一體化方案,將前后端分離,前端項(xiàng)目部署到ecs上,后端api繼續(xù)使用FC。
第三階段 優(yōu)化
分離之后白屏問(wèn)題消失了,前端頁(yè)面很快展示。但是API依然存在首次啟動(dòng)慢的問(wèn)題,導(dǎo)致首次訪問(wèn)時(shí)候,數(shù)據(jù)加載中的loading時(shí)間較長(zhǎng),這也是讓用戶難以接受的體驗(yàn)。
為了解決首屏內(nèi)容加載慢,采用了前端預(yù)渲染的方案。
但前端預(yù)渲染只能解決首屏加載慢,從首屏繼續(xù)訪問(wèn)其他頁(yè)面、從其他頁(yè)面退回首屏,都可能因?yàn)镕C首次啟動(dòng)慢而導(dǎo)致需要用戶長(zhǎng)時(shí)間等待的情況。
因此又采取了數(shù)據(jù)預(yù)下載的優(yōu)化方案。
預(yù)渲染和數(shù)據(jù)預(yù)下載不能保證每次成功,因?yàn)楸镜卣?qǐng)求接口時(shí)間也不固定,即使設(shè)置為60s,也還是存在FC接口沒(méi)有幾十響應(yīng)的情況,因此每次本地構(gòu)建完,都需要手動(dòng)檢查一下(如果自動(dòng)化檢查,當(dāng)項(xiàng)目更新,也還要更新檢查腳本),這讓項(xiàng)目變得不好維護(hù)。
每次后臺(tái)數(shù)據(jù)更新,都要重新構(gòu)建,以保證首屏渲染數(shù)據(jù)是最新的。
前后端拆分還要注意一個(gè)問(wèn)題是跨域訪問(wèn)問(wèn)題
本地支持跨域cookie設(shè)置和訪問(wèn),需要服務(wù)器設(shè)置header:access-allow-control-credentials為"true",并設(shè)置access-allow-control-origin為指定的origin,前端xhr.withCredentials設(shè)置為true。另外前端需要通過(guò)ip訪問(wèn),請(qǐng)求后端接口也需要通過(guò)ip訪問(wèn)。注意有些瀏覽器(如chrome)默認(rèn)設(shè)置cookie的samesite為"lax",且拒絕接受不為secure的samesite為"none"的cookie,sucure必須設(shè)置為“true”,即https訪問(wèn)。
本地調(diào)試,如果前端項(xiàng)目和后端項(xiàng)目都用ip訪問(wèn),即使端口不同也不會(huì)導(dǎo)致跨域,因此我們通過(guò)ip訪問(wèn)本地項(xiàng)目就可以前后端調(diào)試了。
最后 放棄
注意到這時(shí)候系統(tǒng)已經(jīng)漸漸變得復(fù)雜起來(lái)。
除了項(xiàng)目更加復(fù)雜,F(xiàn)C還有一個(gè)讓人頭疼的特性:IP不固定,這個(gè)很好理解,因?yàn)閷?shí)例都是動(dòng)態(tài)管理的,IP不固定的話對(duì)于Serverless平臺(tái)更好管理。這個(gè)特性導(dǎo)致API放在FC時(shí)候,在和其他開放平臺(tái)交互的場(chǎng)景(如微信公眾后臺(tái))需要特殊處理,如果API server需要調(diào)用微信的接口,必須在微信公眾平臺(tái)配置服務(wù)器的IP白名單,但是FC實(shí)例IP不固定,沒(méi)有辦法配置白名單,對(duì)于這種情況,F(xiàn)C給出的建議是,通過(guò)一個(gè)擁有固定IP代理服務(wù)器發(fā)送請(qǐng)求,這就增加了系統(tǒng)的復(fù)雜度,而且還需要額外購(gòu)買服務(wù)器。
還有一個(gè)問(wèn)題,由于使用FC實(shí)現(xiàn)API,實(shí)例是并發(fā)的、動(dòng)態(tài)的,對(duì)于在內(nèi)存中保存多個(gè)接口共享的數(shù)據(jù)的場(chǎng)景(雖然這樣做不推薦),F(xiàn)C就無(wú)能為力了,在靈題庫(kù)網(wǎng)站中,為了實(shí)現(xiàn)驗(yàn)證碼登錄,只好采用了token的方式。
因?yàn)榇嬖谶@些問(wèn)題,對(duì)于輕量的、資金投入受限的網(wǎng)站,后續(xù)還是想把API從FC上遷出來(lái),用Go重構(gòu)到ECS上面。
總結(jié)
下面總結(jié)下使用Serverless搭建網(wǎng)站大半年的個(gè)人的感受,在web開發(fā)場(chǎng)景說(shuō)說(shuō)Serverless對(duì)于前端的機(jī)會(huì)。
FaaS是后端服務(wù)運(yùn)行環(huán)境,簡(jiǎn)化后端運(yùn)維,但對(duì)于小型的應(yīng)用,不用考慮并發(fā),其運(yùn)維成本和ESC差不多,而且在一些場(chǎng)景還更麻煩(如它沒(méi)有固定ip,不能在內(nèi)存中存儲(chǔ)狀態(tài))。只適合有一定規(guī)模的大型應(yīng)用的使用。而Serverless普及程度不高,目前沒(méi)聽說(shuō)有公司全站上Serverless的,因此前端想通過(guò)Serverless轉(zhuǎn)全棧還是不太現(xiàn)實(shí)。
BaaS可以繞過(guò)后端服務(wù),可以開發(fā)一款獨(dú)立應(yīng)用,因此對(duì)于前端想開發(fā)獨(dú)立產(chǎn)品,可以選擇BaaS產(chǎn)品,還省去了聯(lián)調(diào),提高開發(fā)效率。但同樣普及度不高,因此在提高職場(chǎng)競(jìng)爭(zhēng)力方面還是沒(méi)什么空間。
結(jié)論:對(duì)于純前端(沒(méi)有太多后端運(yùn)維經(jīng)驗(yàn)),可以學(xué)習(xí)Serverless作為技術(shù)儲(chǔ)備,但不建議作為提高核心競(jìng)爭(zhēng)力的方向。