Serverless往事(二):前后端分離

前情回顧

上一期《serverless往事:從零搭建一個(gè)web應(yīng)用》被要求整改了。整改完與這一期同時(shí)發(fā)布。新搭建的互聯(lián)網(wǎng)Web應(yīng)用改名為E-Pub,HR母系統(tǒng)就叫做IVF。

這一期里我將E-pub前后端做了分離,并將從前端框架、通信、緩存、ORM逐層介紹新的技術(shù)棧。同時(shí)也會(huì)有一些小小的吐槽。

前端框架之Nuxt.Js

上一期提到了VUE的服務(wù)端渲染(SSR)框架Nuxt。網(wǎng)上討論SSR的時(shí)候往往只專注于首頁渲染和SEO,我個(gè)人覺得后端渲染的最大優(yōu)點(diǎn)是配置簡(jiǎn)單,易學(xué)易用。這可能也是我們廠一直以來偏好后端渲染的某種原因吧,從后端HTML拼接,到j(luò)sp,到IVF使用的thymeleaf,起步階段并不需要太多學(xué)習(xí)成本。(我的Nuxt并非繼承于IVF,因?yàn)镋-pub只是支線業(yè)務(wù),總監(jiān)們可能并不知道我的技術(shù)棧)但是起步簡(jiǎn)單并不見得坑少,IVF就懶得噴了,我們的Nuxt也是一個(gè)深坑,其中讓我最頭疼的問題就是部署。lambda的部署時(shí)有一個(gè)磁盤限制:Package必須同時(shí)滿足壓縮狀態(tài)下小于50M解壓后小于250M這兩個(gè)條件。而Nuxt的Package天生巨大,這讓我一度想轉(zhuǎn)到SPA(single page web application)模式。當(dāng)然SPA也有自己的坑,后期實(shí)踐也發(fā)現(xiàn)了一些難題:比如前端日志搜集、History Mode配置、首頁渲染、webpack的學(xué)習(xí)成本等等。

所幸的是Nuxt2適時(shí)release了,體量大幅減少,然后組里的一個(gè)小朋友分離了前后端,減少了依賴,將package的體積限制在了100余M,總算暫時(shí)渡過了難關(guān)。

通信之Graphql

那時(shí)Graphql v.s. Rest的話題已經(jīng)大火,各種公眾號(hào)狂推Graphql。我在仔細(xì)閱讀過Graphql開發(fā)文檔后立馬決定試水新技術(shù)。這時(shí)公司里又是另一番景象,鮮有人聽聞Graphql,所以我還特地做了一個(gè)廠內(nèi)的技術(shù)分享《Graphql Trial》,可惜并沒有一個(gè)領(lǐng)導(dǎo)來聽。Graphql最吸引我的地方是代碼即文檔,主要還是因?yàn)閼邪?;IVF(對(duì),就是我們的母系統(tǒng))中就碰到過這種事,各種胡亂定義、是似而非的rest api,根本沒人維護(hù)。我當(dāng)時(shí)就一個(gè)光桿司令,與其提出一些不切實(shí)際的document要求,搭建一個(gè)沒人維護(hù)的swagger服務(wù)器,還不如一開始就放棄Restful。除此之外Graphql在復(fù)雜查詢、Mock、類型檢查等等操作上與Rest相比有壓倒性優(yōu)勢(shì)。后來我甚至將Graphql服務(wù)單獨(dú)作為各個(gè)微服務(wù)的收集器用于前端調(diào)用,這是后話了。以下是2018年Javascirpt數(shù)據(jù)層的主流框架,以今年的趨勢(shì),不出意外2019年graphql就應(yīng)該登頂了。

2018 JS趨勢(shì)報(bào)告之?dāng)?shù)據(jù)層

Cache之 DataLoader

我第一篇博客介紹的就是DataLoader。DataLoader的主要功能有兩點(diǎn):

  1. 內(nèi)存級(jí)緩存
  2. 批處理

我當(dāng)時(shí)引入DataLoader的主要目的是減少Dynamodb的資費(fèi),因?yàn)镈ynamodb有單位讀寫限制。后來發(fā)現(xiàn)Cache層本身就意義重大:

  • 解決Graphql N+1 Problem
  • 減少DB讀寫
  • 加速前端數(shù)據(jù)讀取
  • 臨時(shí)存儲(chǔ)preview數(shù)據(jù)

但緩存也帶來一些不可避免的負(fù)面因素,比如臟數(shù)據(jù)。因此在編寫緩存策略時(shí)要設(shè)置expiry time和max size,但即便如此也不可能完全杜絕負(fù)面影響。很多時(shí)候架構(gòu)就是一種權(quán)衡,兩害相權(quán)。

ORM之Dynamoose

Dynamodb的操作也是一堆坑。AWS提供了一套原生的Javascript SDK,大體寫法如下,及其難用!每次都要指定table、key,然后再通過params傳值。此外,最大的困擾是:javascript和Dynamodb都是非強(qiáng)類型的,你會(huì)有一種特別的不安全感,因?yàn)槿魏晤愋?、任何域都能往DB里塞。表結(jié)構(gòu)及其混亂,不具備很強(qiáng)的工程實(shí)踐性。

var params = {
  TableName: 'Table',
  IndexName: 'Index',
  KeyConditionExpression: 'HashKey = :hkey and RangeKey > :rkey',
  ExpressionAttributeValues: {
    ':hkey': 'key',
    ':rkey': 2015
  }
};

var documentClient = new AWS.DynamoDB.DocumentClient();

documentClient.get(params, function(err, data) {
   if (err) console.log(err);
   else console.log(data);
});

被惡心一段時(shí)間后,我把es6換成了Typescript,并開始使用Dynamoose代替原生的SDK。Dynamoosejs引入了schema的概念(受Mongoose啟發(fā)),與table列一一對(duì)應(yīng)。工程中,可以很直觀地見識(shí)到表結(jié)構(gòu)。

const schema = {
  hkey: {
    hashKey: true,
    type: String,
  },
  rkey: {
    rangeKey: true,
    type: Number,
  },
  // Other columns...
  status: String,
}

dynamoose.model(Table_Name, schema).get(key);// return Promise

架構(gòu)改進(jìn)

加入新的技術(shù)棧后我調(diào)整了一下架構(gòu),IVF依舊通過輪詢Rest Api調(diào)用E-pub后端,E-pub前端nuxt則通過單點(diǎn)/grapql訪問后端;后端則對(duì)互聯(lián)網(wǎng)屏蔽所有/api。

New architecture

說到這里我吐槽一下,很多人都有一種烏托邦的幻想,特別崇拜頂層設(shè)計(jì),以為神祗畫一個(gè)圈就可以天下大治。我不相信這些傳說,我更愿意相信由下而上的自發(fā)改良。架構(gòu)設(shè)計(jì)中也是這樣,并沒有神祗架構(gòu)通配一切。反倒是在人力、設(shè)備、管理、技術(shù)都不適配的情況下強(qiáng)推過于復(fù)雜的架構(gòu),更容易帶來毀滅性的結(jié)果。下面是書上看來的一些架構(gòu)設(shè)計(jì)原則:

  • 簡(jiǎn)單優(yōu)于復(fù)雜
  • 合適優(yōu)于時(shí)髦
  • 迭代演化優(yōu)于一步到位。

把握好這些尺度,架構(gòu)設(shè)計(jì)才能真正幫助解耦軟件開發(fā)中的高復(fù)雜度。

小結(jié)

這一期回憶了我在工程起步后對(duì)架構(gòu)的一些調(diào)整。層級(jí)很簡(jiǎn)單,但是新架構(gòu)運(yùn)行的還算良好。很快這一套基礎(chǔ)框架就在組里被大力推廣,PC端、mobile端、line端同步展開。我一個(gè)人的項(xiàng)目迅速擴(kuò)展到了十幾人。
越來越多的新功能被要求集成到serverless里,老的架構(gòu)似乎又開始面臨新的問題,這回我們又該如何變化呢?To be continue....

相關(guān)博客:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容