本文由 IMWeb 首發於 IMWeb 社區網站 imweb.io。點擊閱讀原文查看 IMWeb 社區更多精彩文章。html
導語:提及當前最火的技術,除了最新的區塊鏈,AI,還有一個不得不提的概念是Serverless。Serverless做爲一種新型的互聯網架構直接或間接推進了雲計算的發展,從AWS Lambda到各廠商爭先推出Serverless服務框架,Serverless一路高歌。在這個風口,前端好像都要作點什麼?
前端
1、Serverless簡介node
2、一個輕量web Application遷移實踐linux
本章簡單介紹一下Serverless的演變過程、Serverless是什麼,其優缺點以及適合的應用場景。git
雲計算的發展從IaaS,PaaS,SaaS,到最新的BaaS,FasS,在這個趨勢中serverless(去服務器化)愈來愈明顯。github
Bare Metal(IDC):web
物理機託管redis
IAAS:docker
IaaS(Infrastructure as a Service) 基礎設施即服務,__服務商提供底層/物理層基礎設施資源(服務器,數據中心,環境控制,電源,服務器機房),用戶須要經過IaaS提供的服務平臺購買虛擬資源,選擇操做系統,安裝軟件,部署程序,監控應用。數據庫
目前知名的IaaS平臺有AWS,Azure,Google Cloud Plantform,騰訊雲服務,阿里雲以及開源的OpenStack等。
PAAS:
PaaS(Platform as a Service) 平臺即服務,服務商提供基礎設施底層服務,提供操做系統(Windows,Linux)、數據庫服務器、Web服務器、負載均衡器和其餘中間件,相對於IaaS客戶僅僅須要本身控制上層的應用程序部署與應用託管的環境。
目前知名的PaaS平臺有 Amazon Elastic Beanstalk,Azure,Google App Engine,騰訊容器服務,VMware Cloud Foundry等。
BAAS:
BaaS(Backend as a Service) 後端即服務,服務商爲客戶(開發者)提供整合雲後端的服務,如提供文件存儲、數據存儲、推送服務、身份驗證服務等功能,以幫助開發者快速開發應用。
FAAS:
FaaS(Function as a Service) 函數即服務,服務商提供一個平臺,容許客戶開發、運行和管理應用程序功能,而無需構建和維護基礎架構。按照此模型構建應用程序是實現「無服務器」體系結構的一種方式,一般在構建微服務應用程序時使用。
虛擬化與隔離
從最先的物理服務器開始,咱們都在不斷地抽象或者虛擬化服務器。
服務器發展
咱們使用 XEN、KVM等虛擬化技術,隔離了硬件以及運行在這之上的操做系統。咱們使用雲計算進一步地自動管理這些虛擬化的資源。咱們使用 Docker 等容器技術,隔離了應用的操做系統與服務器的操做。如今,咱們有了 Serverless,咱們能夠隔離操做系統,乃至更底層的技術細節。
無狀態
但也決定了Serverless的無狀態特性,由於每次函數執行,可能使用的都是不一樣的容器,沒法進行內存或數據共享。若是要共享數據,則只能經過第三方服務,好比 Redis,COS 等。
無運維
使用 Serverless 咱們不須要關心服務器,不須要關心運維。這也是 Serverless 思想的核心。
事件驅動編程Serverless 的運行才計算,便意味着他是事件驅動式計算。
低成本
使用 Serverless 成本很低,由於咱們只須要爲每次函數的運行付費。函數不運行,則不花錢,也不會浪費服務器資源。
在 Serverless 應用中,開發者只須要專一於業務,剩下的運維等工做都不須要操心
Serverless 是真正的按需使用,請求到來時纔開始運行
Serverless 是按運行時間和內存來算錢的
Serverless 應用嚴重依賴於特定的雲平臺、第三方服務
Serverless 是一種 「無服務器架構」,讓用戶無需關心程序運行環境、資源及數量,只要將精力 Focus 到業務邏輯上的技術。
FAAS(函數即服務) + BAAS(後臺即服務) 能夠稱爲一個完整的 Serverless 的實現。
Serverless Cloud Function(SCF)架構
Python 2.7 & 3.六、Node.js 6.10 & Node.js 8.九、Java 八、Php 5 & Php 七、Go 1.八、C#&C++(規劃中)
下降啓動成本
減小運營成本
下降開發成本
實現快速上線
更快的部署流水線
更快的開發速度
系統安全性更高
適應微服務架構
自動擴展能力
不適合有狀態的服務
不適合長時間運行應用
徹底依賴於第三方服務
冷啓動時間較長
缺少調試和開發工具
發送通知
WebHook
輕量級 API
物聯網
數據統計分析
Trigger 及定時任務
精益創業
Chat 機器人
雖然目前來講Serverless仍是有很多的侷限性,Serverless一直在發展完善中,廣大開發者和服務提供者都在尋找Serverless的無限可能。
本章基於騰訊雲函數從架構遷移和開發部署流程去說明一個Web Application的遷移實踐。
咱們先來看看一個通常Web Application在SCF上的的架構。
靜態資源
靜態資源(JS/CSS/IMG/HTML)放在COS(對象存儲),COS能夠自定義域名和開啓CDN加速(具體請查看騰訊雲文檔《配置自定義域名支持 HTTPS 訪問》),經過URL直接訪問,這和原來的Web Application沒有什麼區別。
若是咱們是一個單頁面異步應用,也就是咱們的頁面html也是靜態資源,你能夠選擇放在SCF中去返回,就像一個普通的web server返回靜態資源同樣,可是純靜態資源用SCF去返回總以爲大材小用,既耗費了運行資源,性能也不夠好。還能夠放在COS上去存儲,而且COS也能夠支持自定義域名和開啓CDN加速。
可是這樣一來主域和動態數據的域名就存在跨域的問題,經過下面的方法就能夠輕易解決這個問題。
支持跨域訪問:能夠經過API網關設置支持CORS或者後端程序設置CORS。
性能優化:在頁面中header頭中使用preconnect進行動態API的預鏈接,能夠大大減小DNS/TCP/SSL的時間,別小看這個時間,由於目前騰訊雲的雲函數對應的API網關只支持一地接入,地域比較遠的地方,這個時間能夠達到幾百ms。
API網關+應用邏輯
從原來的nodeServer到雲函數的架構變化主要以下:
其中API GATEWAY EVENT的格式
你能夠選擇在代碼中直接去解析使用API GATEWAY EVENT,以及封裝HTTP響應體。HTTP基本上使用獲得的相關的數據字段,API GATEWAY EVENT中字段都有,只是以不一樣的數據結構出現。若是咱們已經很習慣express的開發框架,並且很依賴一些好用的中間件,若是咱們須要重建這部分中間件,這會是不小工做量。--那咱們有沒有方案兼容原來的寫法?
不管是遷移仍是新開發的項目其實均可以採用這個架構:
咱們能夠將API網關事件轉換成http請求,經過本地socket和函數起nodeserver進行通訊。
那麼中間通過了一層服務的轉發,性能會不會有所損耗呢?在統計耗時來看,有了這一層轉發,總共雲函數平均耗時也在20ms以內,那麼中間即便有性能損耗也在10ms以內了,並且是經過本地的socket進行通訊的,相對於網絡耗時來講,就是大巫見小巫了。
中間轉發代理層已經有一些可用的框架(serverlessplus, scf-framework),你們能夠嘗試一下,用法都比較簡單。
數據存儲
因爲Serverless的架構是事件觸發,用完即釋放,那麼你必定要考慮的是,你的本地存儲和緩存必須依賴於第三方服務如cos和redis,不過能夠經過實例保留或者它自己會有3分鐘的釋放延遲時間,你依然能夠利用本地存儲和內存緩存做爲你的第一級緩存。
一、DB
和原來的DB使用沒有太大的區別。
通常咱們選擇與公司內網打通的VPC內申請資源,這樣安全係數比較高,與外網徹底隔離,經過選擇相同的子網,才能連通。
資源申請在下文開發部署篇會說到。
也能夠選擇純外網的DB資源,而後經過創建虛擬子網,和騰訊雲函數設置同一個子網內,雲函數就能夠經過內網IP進行訪問。另外DB也能夠設置外網域名地址,經過外網訪問,這樣本地開發的時候也能夠訪問到了,通常測試時使用。
數據庫實例界面:
二、內存緩存
如上面所說,實例會有一個延遲銷燬時間,若是短期內命中同一個實例,實例中內存變量是能夠被緩存住的。須要緩存的內容能夠兩級緩存,先從內存中讀取,讀取不到再到Redis中讀取。
Redis的使用和DB相似,申請資源,設置子網,經過IP PORT進行鏈接使用。
能夠經過下面封裝的npm包進行Redis簡單使用。
npm i qcloud-serverless-redis
三、文件存儲
Serverless可寫的目錄是/tmp/, 可是會隨着實例釋放而釋放,因此只能臨時放一下。
總共大小隻有512M,建議臨時文件用完要主動刪除。
若是要長期存儲的文件,可使用COS進行存儲。
具體COS操做能夠參考騰訊雲文檔 如:Node.js SDK 快速入門
我這裏也簡單封裝了一個cos的npm包,能夠快速嘗試一下cos的存取功能,具體用法看裏面的README
tnpm i@tencent/serverless-cos
登陸相關
這個解決方案同數據存儲相似,能夠經過第三方服務來保存狀態或者經過token加解密來進行狀態保存。
下面這個方案是經過token的加解密來進行登陸狀態檢查的,登陸驗證過程是調用了原有的後臺服務。
而小程序是沒有cookie這個概念的,也就是小程序不會幫你set-cookie,保存cookie,發送cookie,這些都須要你本身模擬來作。如今的通用方案通常是前端接收後端返回的內容,保存在localStorage中,每次請求的時候校驗有效期,並將token設置到header中的cookie模塊,後端能夠正常拿到cookie進行驗證。
性能調優
第一章說到Serverless其實不適合對時延有比較高要求的場景,那麼實際上性能如何,是否有優化的空間,是否可以知足咱們的即時響應的需求呢?
咱們先來看一下一個雲函數啓動的過程,包括哪些步驟。
函數發生調用,調度系統看函數實例是否存在,若是實例存在,那麼就能夠執行函數,返回結果。這個時間是很是短的,在毫秒級別。
若是不存在,那麼須要建立容器,下載部署代碼。這些過程耗時百毫秒到幾秒不等,稱爲冷啓動。
優化函數的性能,也就須要從函數生命週期的各個階段去優化。
一、函數實例複用,這是最直接有效的手段。可是保留多長時間合適?3分鐘,能解決95%的問題3小時,能解決99%的問題3天,能解決99.9%的問題。這個是一個成本和效果衡量的問題。(保留時間也不必定是固定不變的值,須要分析函數特色和時間段。)
二、預建立一批不一樣規格的容器(不含代碼)來減小建立容器的耗時。
三、函數平臺有一個代碼倉庫來保存管理函數代碼的,在使用的時候纔會在下載到容器中。能夠對熱點代碼進行緩存:一級:Node計算節點緩存,二級:機房緩存
四、經過機器學習預測流量,預先啓動一些函數實例,這樣就能夠儘可能消除冷啓動,保證明例都是熱啓動的。
這些都是平臺作的優化,那麼開發者能夠作什麼呢?
代碼精簡:縮短代碼下載時間
公共剝離:增長緩存效果,將一些公共的,常調用的服務拆分紅一個獨立的雲函數,能夠增長緩存的效果。
資源複用:縮短執行時間,這裏指的是,函數使用的公共資源能夠放到函數外面來定義執行,好比數據庫的鏈接。
保持活躍:避免資源回收,這就保證了請求都是熱啓動的。
更多能夠參考個人另一篇文章《前端學serverless系列——性能調優》
1)雲上調試
目前發佈到雲函數是要包含node_modules文件夾的,就算不須要,也要壓縮,而後經過網絡傳輸上去。若是改一行代碼,就要上傳一次來執行,那不是要崩潰?並且在線的IDE也是隻能編輯index.js,可是代碼都不是寫在入口文件那的。在線IDE目前只能支持單文件入口函數的編輯,升級IDE也在規劃開發中的。
2)本地調試1.0
須要提早安裝tcf,docker
具體安裝請參考 TCF命令行工具
本地執行命令:
tcflocalinvoke--templatetemplate.yaml--eventevent/apigateway.json
調試起來比第一種方案快了許多,雖然在公司的網絡必定要開一個代理,不然會拉取不下來docker鏡像。
這個運行方式的原理是,加載一個和雲函數環境差很少的一個鏡像,而後在docker中去執行。
然而仍是會遇到很多問題:
好比鏈接的數據庫必定要是外網地址,由於docker的網絡環境和本地並不能連通,與雲上的環境也不能連通。
好比我在本地安裝的npm包,也不能正常執行,由於我本地是mac系統,而鏡像是linux系統。
好比雲函數原本內置了一些npm包,我寫了個腳本,刪除了這部分npm包,在雲上能夠正常執行,在本地調試的時候發現又缺乏npm包,緣由是雲上的環境和鏡像中的環境不安全一致。不過這個問題也已經解決。
3)本地調試2.0
隨着開發者的反饋,雲函數的同事又推出了TCF升級版本。能夠支持native調試,其實就是用本地的環境進行調試。這樣至少鏈接數據庫沒有連通問題,以及調試的時候沒有操做系統差別問題。那麼最後一個問題只能是須要一個專門的編譯機了。通常狀況下,若是依賴的npm庫若是不涉及到操做系統差別的話,npm包都是能夠通用的。
具體用法能夠查看文檔:https://github.com/tencentyun/tcfcli
tcfnativeinvoke--templatetemplate.yaml--eventevent/apigateway.json
4)node server調試:
若是你的項目是基於koa或者express之類的框架,能夠直接增長一個server的入口,本地調試的時候就直接起一個server,和普通node server同樣的進行調試。
可使用tcf命令進行發佈,tcf命令行發佈支持兩種
經過cos對象存儲上傳代碼
經過本地zip包上傳代碼(zip大小不能超過50M)
具體能夠查看文檔:如何用tcf發佈部署代碼
前面說到用命令行工具很方便的將代碼發佈到雲函數平臺上。
//示意代碼
tcfpackage&tcf deloy
可是隻是發佈上去就能夠了嗎?
開發測試和線上環境如何隔離呢,如何回滾呢?
雲函數自己有版本功能,雲函數詳情頁面右上角能夠發佈新版本。
API網關也默認有測試、預發佈、發佈3個環境,能夠指定雲函數的版本。
那麼咱們測試的時候能夠指定$LATEST版本,測試經過以後能夠發一個雲函數的版本,而後配置API網關的預發佈環境進行預發佈驗證,預發佈驗證以後,再發布到線上環境。
具體操做路徑:點擊API網關具體的服務進到詳情頁,在API管理下,針對每一個API進行編輯。
選擇要對應的版本:
編輯完成以後,API須要發佈到對應環境纔會生效。
操做回滾也很方便,直接切換到歷史到版本就能夠。不過要注意的是,寫好備註,不要像我同樣寫「test」 ^_^
到這裏,看起來就能夠將測試和線上的環境區分開。
可是實際上,測試和線上鏈接的資源是不同的,好比DB,咱們一般是經過讀取環境變量來判斷鏈接什麼資源,而不是經過改代碼,而一個雲函數只有一個配置。
那麼咱們能夠利用命名空間來將測試和發佈環境隔離,發佈能夠經過函數複製來完成,可選不復制配置,配置在線上和測試環境設置不同,代碼經過判斷環境變量來鏈接線上和測試的資源。
建立命名空間:
複製函數到其餘命名空間:
設置環境變量:
根據環境變量讀取不一樣到配置:
//根據環境變量讀取不一樣的配置
const devConfig = require('./config.dev');
const testConfig = require('./config.test');
const prodConfig = require('./config.prod');
const env = process.env.NODE_ENV;
console.log('process.env.NODE_ENV', process.env.NODE_ENV);
switch (env) {
case 'prod':
module.exports = prodConfig;
break;
case 'test':
module.exports = testConfig;
break;
default:
module.exports = devConfig;
}
總結一下:
1)測試和線上放在兩個不一樣到命名空間,隔離測試和線上代碼。
2)上線經過複製函數來完成。
3)測試和線上環境經過函數配置設置不一樣的環境變量來區分。
4)回滾經過設置函數版原本完成。
API網關會有一個默認的域名,這讓咱們不須要本身去申請一個域名纔可使用API網關。可是,通常若是是用戶在瀏覽器中訪問的URL,確定是須要本身/簡短點的域名更讓人信任。
API網關-自定義域名
若是是支持https的話,須要在騰訊雲上上傳https證書。
另外,還能夠自定義路徑映射,好比將發佈的路徑從 http://yourdomain/release 到 http://yourdomain/ 訪問更簡短。也能夠將/test測試路徑改得更復雜一些,避免用戶訪問到,固然你不發佈測試環境更保險。
涉及到後臺服務,那麼日誌的打印是必不可少的,調試,查問題,甚至統計可能都須要用到日誌。那麼雲函數的日誌能夠怎麼來使用呢?
在雲函數的界面,我看能夠看到一個雲函數的日誌界面,能夠支持實時日誌顯示,還有選擇時間,還有隻選擇失敗的日誌。
可是咱們看到惟一的檢索框,只能根據RequestID來檢索,每一個請求有一個RequestID。那麼requestID去哪裏獲取,貌似只能從這條日誌中去獲取,若是你傳給了其餘服務或者前端,其餘服務追查問題的時候,能夠追溯到這裏。
這明顯太不方便了。
日誌服務在我用的時候尚未出,在我寫這篇文章的時候已經上線了。
若是當前函數已經配置了日誌服務,能夠[前往日誌服務]對日誌進行更方便的檢索。
在函數配置界面下方,能夠配置將日誌投遞到日誌服務。新建日誌服務
建立日誌集:
日誌集上能夠建立多個日誌主題。
一個日誌能夠如何消費呢,能夠看下下面到這個操做欄:
LogListener是用於有本身到服務器的採集方式,而云函數的採集只須要在函數配置中指定一下要投遞的日誌集和日誌主題便可。
索引配置:能夠配置分詞符
投遞配置:能夠將日誌投遞到COS
實時消費:能夠用Ckafka消費
檢索示例:
雲函數和API網關有一些自帶的監控,能夠知足查看需求,若是須要更詳細的視圖配置和告警功能的話,可使用雲監控。
雲函數首頁總覽:
雲函數監控信息界面:
API網關監控:
若是須要更加豐富的統計監控告警,能夠查閱雲監控
其中自定義監控對後臺服務來講也是很是須要的,能夠上報一些業務類型的指標或者告警。可查看文檔:自定義監控
注意事項
一、項目中用到的node_modules還不能在線安裝,只能從本地打包上傳。
二、不少人本地的開發環境是windows或者是mac,有一些nodemodule依賴是和操做系統相關的,那麼在本地安裝的nodemodules,在雲函數上或鏡像中並不能使用。
三、本地調試的docker環境是網絡隔離的,那麼若是你要鏈接相關的baas服務,那麼你須要支持外網訪問的baas服務。若是是node的話,已經能夠支持tcf native 來調試,不用docker調試了。
四、服務端設置cookie目前只能設置一個。這個騰訊雲也在計劃修復中。
等~
最後
咱們如今使用HTTP協議的時候,須要經過API GATEWAY中轉一層,能不能去掉這一層中轉呢?
若是咱們的業務應用比較複雜的話,須要拆成多個雲函數來承載,對於這樣的現有項目能不能0改造遷移呢?
如今部署雲函數的時候,須要將lib庫也打包上傳,咱們但願能和代碼倉庫打通,在git push的時候,可以在線編譯,而且自動部署。
這些問題將會在騰訊雲serverless2.0中解決,即將發佈,不妨期待一下。
嘗試的路還在繼續,歡迎有興趣有需求的開發者一塊兒討論一塊兒探索一塊兒建設。