前言
Serverless是近些年來流行起來的架構(gòu)理念,進入市場化應(yīng)該是2014年亞馬遜發(fā)布FaaS Lambda。
一個熱詞的產(chǎn)生,必然會有一些商家搶注商標(biāo)的現(xiàn)象,所以,我們目前搜索Serverless,搜索結(jié)果第一頁會看到名為Serverless的產(chǎn)品。
我們?nèi)粘Uf的Serverless,一般是指架構(gòu)理念,或基于架構(gòu)理念產(chǎn)生的產(chǎn)品全類,而非指某個具體的產(chǎn)品。
Serverless是對運維體系的極端抽象,這里有一個名次“抽象”、兩個定語“運維體系的”、“極端”。
-
Serverless是一個抽象,就說明Serverless不是指具體的某個產(chǎn)品。 - "運維體系的",說明了
Serverless的職能邊界,是對運維體系流程的優(yōu)化,當(dāng)然,也對開發(fā)流程產(chǎn)生了一些副作用,但,主要的職能在運維方向。 - "極端抽象",是表明基于
Serverless理念輸出的產(chǎn)品,將運維體系的復(fù)雜度內(nèi)化,只預(yù)留簡單的接口供外部調(diào)用。
帶來的結(jié)果就是,可以讓零運維經(jīng)驗的人,幾分鐘就部署一個Web應(yīng)用上線,稍后我會在==示例==中演示一下。
運維發(fā)展史

先看一下整個發(fā)展流程,經(jīng)歷了手動運維、自動運維、DevOps開發(fā)運維、智能運維幾個階段。
按社會的精細(xì)化分工來說:
- 手動運維階段,開發(fā)者交付代碼,運維團隊需要進行服務(wù)器協(xié)調(diào)、運行環(huán)境部署、上線、版本控制、日志監(jiān)控、擴縮容設(shè)計、容錯容災(zāi)高可用設(shè)計...等等工作。
- 如果線上產(chǎn)品出現(xiàn)問題,需要開發(fā)者和運維團隊共同查找問題。
- 自動運維階段,通過編排腳本命令將一些簡單的工作進行打包處理,一定程度上減少重復(fù)性的手工操作。
- 隨著微服務(wù)、容器技術(shù)的發(fā)展,來到了
DevOps階段,DevOps=Development+Operations,開發(fā)者開始承擔(dān)一部分的運維職責(zé),甚至有些公司出現(xiàn)了跨職能團隊:運維、開發(fā)團隊融合,打破手動運維階段開發(fā)、運維兩座孤島的現(xiàn)象。這個階段,就Docker工具而言,開發(fā)者交付鏡像,運維團隊不必在操心代碼的運行環(huán)境問題。 - 智能運維階段,
Serverless只是其中的一個發(fā)展節(jié)點。- 各大服務(wù)廠商將基礎(chǔ)設(shè)施云化,對外提供接口,實現(xiàn)基礎(chǔ)設(shè)施即代碼,讓開發(fā)者可以通過應(yīng)用程序代碼訪問、配置基礎(chǔ)設(shè)施(BaaS:抽象粒度大多在機器級別)。
- 計算機算力的提升,如函數(shù)計算[阿里云]、云函數(shù)[騰訊云]將計算服務(wù)的抽象粒度提高到了函數(shù)級別,實現(xiàn)實時的彈性伸縮容機制,按毫秒級計量、按需計費(FaaS)。
產(chǎn)生背景
- 從整個發(fā)展史可以看出,技術(shù)的發(fā)展起到了重要的推動作用。
- 歷史運維體系的痛點:企業(yè)中長尾應(yīng)用的運營成本問題。
- 什么是中長尾應(yīng)用?就是每天大部分時間沒有流量或者有很少流量的應(yīng)用
- 為了保證這些應(yīng)用的正常運行,至少要安排一臺服務(wù)器跑這些應(yīng)用。
- 而
Serverless借助計算機算力,可以實現(xiàn)實時的彈性擴縮容機制。
- 減少研發(fā)人員的關(guān)注點,研發(fā)人員無需管理、維護底層的基礎(chǔ)設(shè)施,無需規(guī)劃預(yù)估容器所需要的計算資源,降低整合和決策的代價,只需要專注應(yīng)用程序代碼的編寫,提高研發(fā)效能。
下個定義
狹義Serverless = FaaS架構(gòu)
狹義的Severless是指基于函數(shù)計算將Serverless體系產(chǎn)品整合在一起,構(gòu)建成一個Serverless應(yīng)用。
狹義Serverless = FaaS架構(gòu) = Trigger + FaaS + BaaS = FaaS + Baas
廣義Serverless是指具備Serverless特性的云服務(wù)。
Serverless可以分為Server和less,其中less不是指無服務(wù)器端,或者少服務(wù)器端,而是指無感知,也對應(yīng)了“Serverless是對運維體系的極端抽象”這句話。
發(fā)展現(xiàn)狀
目前大多數(shù)互聯(lián)網(wǎng)公司都還在DevOps時代。
部分一線大廠有自己的Serverless解決方案并對外開放。如阿里云的函數(shù)計算、騰訊云的云函數(shù)。
目前Serverless架構(gòu)實現(xiàn)并沒有統(tǒng)一的規(guī)范,實現(xiàn)和提供服務(wù)的廠商強關(guān)聯(lián),如果在不同廠商之間遷移,會有很大的工作量和困難。
函數(shù)計算
以阿里云平臺的函數(shù)計算來介紹一下FaaS函數(shù)即服務(wù)。
我們先熟悉一下平臺設(shè)計。
- 可以通過支付寶掃碼授權(quán)登陸。
- 直接用“產(chǎn)品”菜單下的搜索功能搜索“函數(shù)計算”。
- 點擊“控制臺”直接進入。
- 頂部
- 可以切換代碼部署的地域
- 如果在“服務(wù)/函數(shù)”下找不到自己已有的代碼,檢查一下地域是否選擇正確。
- “概覽”頁面
- 可以直觀的看到使用量、監(jiān)控的概覽,還有一些快捷入口。
- 免費執(zhí)行次數(shù)和免費資源使用量,在測試階段可以有效的防止用超過,也很難用超過。
- 監(jiān)控的可視化圖形
- 新建函數(shù)的快捷入口
- “服務(wù)及函數(shù)”
- 可以創(chuàng)建新服務(wù)、新函數(shù),查看已有服務(wù)和函數(shù)。
- 點擊服務(wù)列表中的某項,可以在右側(cè)查看、編輯包含的函數(shù)列表、服務(wù)相關(guān)的配置信息。
- 點擊函數(shù)列表中的某項,可以進入函數(shù)詳情,查看、配置函數(shù)的信息。
- 自定義域名
- 通過自定義域名訪問FC函數(shù),需要配合HTTP觸發(fā)器使用
- ==HTTP觸發(fā)器==后續(xù)講函數(shù)類型的時候會提到。
FaaS
下面我們具體看一下函數(shù)計算。
首先,我們創(chuàng)建一個服務(wù)、一個函數(shù)。
創(chuàng)建好一個服務(wù)以后,默認(rèn)打開“服務(wù)配置”Tab,從該Tab頁,我們可以查看服務(wù)當(dāng)前的配置并進行修改。
切換到“函數(shù)列表”Tab頁,點擊新增函數(shù)按鈕,這時會發(fā)現(xiàn),函數(shù)有兩類:
- 事件函數(shù)
- HTTP函數(shù)
這里HTTP函數(shù),就是上邊所說,有HTTP觸發(fā)器的函數(shù),可以通過網(wǎng)絡(luò)請求觸發(fā)FC函數(shù)的執(zhí)行;
因為上邊我們提到了HTTP觸發(fā)器,那就先創(chuàng)建一個HTTP函數(shù)。
創(chuàng)建成功后,默認(rèn)進入函數(shù)的“觸發(fā)器”Tab頁,可以看到“事件類型”是http,請求方法是GET、POST,不需要授權(quán)訪問。
為了更清晰的看到觸發(fā)器的配置項,我們重新創(chuàng)建一個觸發(fā)器。
然后,切換到“代碼執(zhí)行”Tab頁,我們可以看到示例代碼。
HTTP函數(shù)示例代碼:
- 結(jié)構(gòu):exports.handler = (req, resp, context) => {}
- 函數(shù)調(diào)用時,執(zhí)行定義的handler邏輯,參數(shù)是req、resp、context;
- 這些參數(shù)后續(xù)==調(diào)試階段==我們可以看一下
- 打印標(biāo)準(zhǔn)版的輸出
hello world - 組裝請求數(shù)據(jù)字段
- 將
body數(shù)據(jù)提取并輸出組裝的數(shù)據(jù)
我們執(zhí)行一下看看會發(fā)生什么?
- 打印返回的結(jié)果
- 打印函數(shù)執(zhí)行日志
- 打印
RequestID- 這是唯一存在的ID,每次執(zhí)行都會改變。
- 可以通過該ID查詢?nèi)罩尽?/li>
在“執(zhí)行”按鈕處,可以配置一些參數(shù),改變一下配置看看輸出的結(jié)果。
-
POST請求 - 路徑
-
Params改變URL上的過濾參數(shù) -
Body改變POST的請求輸出,GET請求下不會出現(xiàn)該Tab頁
而且,在修改的過程中,會發(fā)現(xiàn)上方的URL會發(fā)生變化。
我們可以通過Postman去請求該地址,調(diào)用FC函數(shù),可以通過“日志查詢”查看調(diào)用結(jié)果。
最后,我們看一下exports導(dǎo)出的函數(shù),默認(rèn)函數(shù)名為handler,這個名字能修改么?
答案是肯定的。
- 切換到“概覽”Tab頁,“修改配置”,修改“函數(shù)入口”
- 切換回“代碼執(zhí)行”,執(zhí)行看一下結(jié)果,報錯
- 將
exports.[fnName]修改成配置項,“保存”,再執(zhí)行,成功。
看完了HTTP函數(shù),我們返回去看一下事件函數(shù)。
返回到服務(wù)列表頁面。
“新增函數(shù)” ——> “事件函數(shù)” ——> “配置部署”
配置頁面:
- 運行環(huán)境
- 彈性實例
- 彈性實例有免費額度
- 性能實例沒有免費額度
- 性能實例擴容速度慢,彈性伸縮能力不及彈性實例:對比文檔
- 函數(shù)入口
- 和“HTTP函數(shù)”一樣,可以修改約定的導(dǎo)出函數(shù)名
點擊“完成”創(chuàng)建函數(shù)。
“HTTP函數(shù)”跳轉(zhuǎn)到“觸發(fā)器”Tab,而“事件函數(shù)”直接跳轉(zhuǎn)到“代碼執(zhí)行”Tab。
切換到“觸發(fā)器”,我們可以看到,沒有任何數(shù)據(jù)。
我們看一下“事件函數(shù)”的實例代碼:
- 結(jié)構(gòu):exports.handler = (event, context, callback) => {}
- 函數(shù)調(diào)用時,執(zhí)行定義的handler邏輯,參數(shù)是event, context, callback;
- 這些參數(shù)我們依舊在后續(xù)==調(diào)試階段==看一下
- 依舊打印標(biāo)準(zhǔn)版的輸出
hello world - 通過callback返回數(shù)據(jù)
- callback(err, data)
- 第一個參數(shù)是錯誤信息
- 第二個參數(shù)是數(shù)據(jù),只有在第一個參數(shù)為
null時,才返回數(shù)據(jù)
代碼的“執(zhí)行”按鈕在上邊,嘗試修改代碼,也能看到是自動保存。
執(zhí)行一下程序看看會發(fā)生什么?
- 打印返回的結(jié)果
- 打印函數(shù)執(zhí)行日志
- 打印
RequestID- 這是唯一存在的ID,每次執(zhí)行都會改變。
- 可以通過該ID查詢?nèi)罩尽?/li>
我們從兩個示例函數(shù)中,都可以看到注釋的exports.initializer函數(shù)。
這個函數(shù)是做什么的呢?
通過函數(shù)名,可以知道,這是實例的初始化函數(shù),保證同一實例成功且僅成功執(zhí)行一次。
值得注意的是:這個函數(shù)沒有返回值。
將“事件函數(shù)”中的注釋去掉,“保存并執(zhí)行”,看看有什么不同。
發(fā)現(xiàn)執(zhí)行結(jié)果和原來沒什么不同,初始化函數(shù)中的console.log('initializing')并沒有打印出來。
要怎么做呢?
要初始化函數(shù)執(zhí)行,需要特殊的配置。
切換到“概覽”Tab,“修改配置” ——> “是否配置函數(shù)初始化入口”,定義為剛剛解注的函數(shù)名,“確認(rèn)”后跳轉(zhuǎn)至“代碼執(zhí)行”。
“執(zhí)行”代碼,查看執(zhí)行結(jié)果:報錯——> 無效的函數(shù)名。
重新“修改配置”,初始化入口定義為index.initialzer即可。
FC Initialize Start RequestId: e8acfe4c-9670-4255-86f1-2659291031c1
load code for handler:index.initializer
2020-12-24T09:13:36.846Z e8acfe4c-9670-4255-86f1-2659291031c1 [verbose] initializing
FC Initialize End RequestId: e8acfe4c-9670-4255-86f1-2659291031c1
會看到函數(shù)執(zhí)行日志中,多出來幾條日志。
連續(xù)多次點擊“執(zhí)行”,也僅僅在第一次執(zhí)行的時候,會多這幾條日志,表明“初始化函數(shù)”僅僅執(zhí)行一次。
修改“初始化函數(shù)”中的callback(null, 123)發(fā)現(xiàn)執(zhí)行日志中并沒有輸出,表明“初始化函數(shù)”沒有輸出。
有沒有疑惑:
var ret = '';
function handlerRet() {
console.log('-------');
ret = 'return success';
}
handlerRet();
exports.handler = (event, context, callback) => {
console.log(ret);
callback(null, 'hello world');
}
上邊這個代碼的執(zhí)行結(jié)果是怎樣的?
和“初始化函數(shù)”有什么不同?
- 執(zhí)行時機不同
- “初始化函數(shù)”在函數(shù)實例初始化之前執(zhí)行;
- 上述看似“全局”的代碼是在實例化之后執(zhí)行的;
- 執(zhí)行次數(shù)
- 上述代碼和“初始化函數(shù)”一樣,都僅執(zhí)行一次;
我們可以看到,上述三種類型的函數(shù)(HTTP函數(shù)、事件函數(shù)、初始化函數(shù))與普通定義的函數(shù)最大的區(qū)別在于,F(xiàn)C的函數(shù)預(yù)置了Context參數(shù),這是和Runtime運行平臺/上下文相關(guān)的參數(shù)。
我們可以通過URL請求去調(diào)用“HTTP函數(shù)”,那如何去調(diào)用“事件函數(shù)”呢?
- 創(chuàng)建觸發(fā)器
- 我們切換到“觸發(fā)器”面板,“創(chuàng)建觸發(fā)器”,以一個最簡單的“定時觸發(fā)器”為例。
- 最小1分鐘時間間隔
- 默認(rèn)“啟動觸發(fā)器”
- 通過“日志查詢”面板,“每分鐘自動刷新”,可以查看執(zhí)行日志(會有延遲)。
- 修改觸發(fā)器的“觸發(fā)消息”:JSON數(shù)據(jù),修改“代碼執(zhí)行”,在入口函數(shù)中打印
event:console.log(JSON.parse(event))查看輸出結(jié)果。- 可以看到,我們可以通過“觸發(fā)消息”傳遞參數(shù)。
- 關(guān)閉“觸發(fā)器”的狀態(tài)
- 我們切換到“觸發(fā)器”面板,“創(chuàng)建觸發(fā)器”,以一個最簡單的“定時觸發(fā)器”為例。
- SDK調(diào)用
- 本地編寫代碼程序
'use strict'; var FCClient = require('@alicloud/fc2'); var client = new FCClient( '<account id>', { accessKeyID: '<access key>', accessKeySecret: '<access key secret>', region: 'cn-beijing', timeout: 10000 // milliseconds, default is 10s } ); async function test () { try { var ret = await client.invokeFunction('case-1.LATEST', 'case-event', 'event') console.log('invoke function: %j', ret); } catch (err) { console.error(err); } } test().then(); -
node invoke/index.js- 可以看到本地終端有日志打印出來,正是代碼中的
console.log('invoke function: %j', ret);執(zhí)行的結(jié)果
- 可以看到本地終端有日志打印出來,正是代碼中的
- 控制臺切換到“日志查詢”,查看執(zhí)行日志,確定FC的函數(shù)被觸發(fā)。
- 本地編寫代碼程序
上述編寫的函數(shù)除了“HTTP函數(shù)”并沒有引入外部依賴,如何引入第三方依賴呢?
其實,“HTTP函數(shù)”引入的依賴是阿里云平臺的Node.js環(huán)境內(nèi)置好的第三方包,如果我們需要使用沒有內(nèi)置的依賴包,需要在本地開發(fā)環(huán)境去安裝、編寫代碼邏輯。
所以,我們接下來說一下本地開發(fā)環(huán)境的配置:
- 安裝
Docker; //編譯代碼、安裝依賴以及在本地運行調(diào)試等操作都是在Docker鏡像中進行; -
Visual Studio Code中查找aliyun serverless插件并安裝;- 安裝過程中需要輸入
account id、access key、access key secret。 - 可以通過阿里云官網(wǎng)賬號一欄找到這些信息。
- 我們會看到
Visual Studio Code右側(cè)面板多出了兩個FC的Logo選項。
- 可以通過界面查看到遠程控制臺創(chuàng)建的服務(wù)及函數(shù)。
- 將遠程服務(wù)及函數(shù)下載到本地
- 從
A區(qū)域,我們可以看到下載到本地對應(yīng)的服務(wù)、函數(shù)及觸發(fā)器列表,點擊列表中的某項,會跳轉(zhuǎn)到template.yml文件對應(yīng)的配置 -
B區(qū)域,是對列表項的操作- 服務(wù):添加函數(shù)操作
- 函數(shù):查看源碼、調(diào)試、執(zhí)行操作
- 觸發(fā)器:無
- 安裝過程中需要輸入
接下來,我們通過代碼調(diào)試先看一下編寫代碼時,遺留的函數(shù)參數(shù)結(jié)構(gòu)的問題,然后再說依賴問題:
查看case-event函數(shù)的源碼,在行號上添加斷點,點擊“調(diào)試”操作
即可查看對應(yīng)的參數(shù)結(jié)構(gòu)。
引入第三方NPM包
- 通過
Visual Studio Code“資源管理器”查看一下case-event函數(shù)所在的路徑 - “終端”切換到函數(shù)對應(yīng)目錄
cd case-1/case-event -
npm init -y初始化環(huán)境 -
npm i -S xss做示例 - 修改代碼
'use strict';
var xss = require('xss');
/*
To enable the initializer feature (https://help.aliyun.com/document_detail/156876.html)
please implement the initializer function as below:
*/
exports.initializer = (context, callback) => {
console.log('initializing');
callback(null, '123');
};
exports.handler = (event, context, callback) => {
console.log('hello world');
var html = xss('<script>alert</script>')
callback(null, html);
}
- 執(zhí)行函數(shù),查看輸出結(jié)果:依賴正常執(zhí)行。
FC Initialize Start RequestId: e2c60d38-bed8-4a92-a48f-56b7c7949d9a
load code for handler:index.initializer
2020-12-25T03:21:47.571Z e2c60d38-bed8-4a92-a48f-56b7c7949d9a [verbose] initializing
FC Initialize End RequestId: e2c60d38-bed8-4a92-a48f-56b7c7949d9a
123FC Invoke Start RequestId: e2c60d38-bed8-4a92-a48f-56b7c7949d9a
load code for handler:index.handler
2020-12-25T03:21:47.651Z e2c60d38-bed8-4a92-a48f-56b7c7949d9a [verbose] hello world
FC Invoke End RequestId: e2c60d38-bed8-4a92-a48f-56b7c7949d9a
<script>alert</script>
- 然后,我們將服務(wù)整體上傳或在函數(shù)上右鍵單獨上傳,替換控制臺的代碼
- 會將依賴
node_modules一起上傳 -
FC函數(shù)所需要的依賴必須一同打包上傳,否則,會報資源查找不到。
- 會將依賴
介紹完阿里云平臺的函數(shù)計算,結(jié)合Serverless的定義思考一下,Serverless=FaaS架構(gòu),Serverless具有實時彈性擴縮容的優(yōu)勢,函數(shù)計算怎么實現(xiàn)這個優(yōu)勢的呢?
這和FC函數(shù)的進程模型有關(guān):
- 服務(wù)托管細(xì)?;搅苏Z言單位,即函數(shù)調(diào)用
- 事件驅(qū)動的計算模型
- 用完即毀型設(shè)計:函數(shù)實例準(zhǔn)備好后,執(zhí)行完函數(shù)就直接結(jié)束。
- 無狀態(tài),不存儲任何狀態(tài)
- 正因為沒有任何狀態(tài),因此在并發(fā)量高的時候,我們可以對無狀態(tài)節(jié)點橫向擴容,而沒有流量時我們可以縮容到 0
剛剛說到FaaS或FC的函數(shù)是無狀態(tài)的,那我們需要狀態(tài)共享的時候,應(yīng)該怎么做?
借助于BaaS: 后端即服務(wù)。
“自定義域名”中,我們可以將編寫的函數(shù)與備案好的域名綁定在一起,這樣,可以通過自定義的域名訪問我們的“HTTP函數(shù)”。
應(yīng)用示例
Nuxt.js應(yīng)用的遷移
- 遷移應(yīng)用需要使用
Funcraft命令行工具npm i -g @alicloud/fun全局安裝; -
fun --version查看版本信息驗證是否安裝成功; - 這里我下載了一個已有的項目,進入項目目錄下,確保
node版本在12.*以上,npm i安裝開發(fā)依賴; -
npm run dev保證我們的項目本地正常運行; -
npm run build編譯項目; -
npm run start保證編譯后的項目能夠正常啟動; -
fun deploy -y部署項目至函數(shù)計算;current folder is not a fun project. Generating /Users/****/Desktop/case/migc-open-act-master/bootstrap... Generating template.yml... Generate Fun project successfully!- 自動生成
template.yml文件ROSTemplateFormatVersion: '2015-09-01' Transform: 'Aliyun::Serverless-2018-04-03' Resources: migc-open-act-master: # service name Type: 'Aliyun::Serverless::Service' Properties: Description: This is FC service migc-open-act-master: # function name Type: 'Aliyun::Serverless::Function' Properties: Handler: index.handler Runtime: custom CodeUri: oss://fun-gen-cn-beijing-***/9c517abf18826f644880440a12eebef7 MemorySize: 1024 InstanceConcurrency: 5 Timeout: 120 Events: httpTrigger: Type: HTTP Properties: AuthType: ANONYMOUS Methods: ['GET', 'POST', 'PUT'] Domain: Type: Aliyun::Serverless::CustomDomain Properties: DomainName: Auto Protocol: HTTP RouteConfig: Routes: "/*": ServiceName: migc-open-act-master FunctionName: migc-open-act-master - 自動生成
bootstrap文件#!/usr/bin/env bash export PORT=9000 npx nuxt start --hostname 0.0.0.0 --port $PORT - 自動生成一個可訪問的臨時域名
Detect 'DomainName:Auto' of custom domain 'Domain' Request a new temporary domain ... The assigned temporary domain is http://38880398-******.test.functioncompute.com,expired at 2021-01-04 15:13:18, limited by 1000 per day. Waiting for custom domain Domain to be deployed... - 自動生成
這兩個文件是做什么的呢?
帶著疑問,我們看Custom Runtime
Custom Runtime
剛剛我們遷移了Nuxt.js應(yīng)用,如果想遷移其它應(yīng)用呢?
遷移應(yīng)用之前,必須要了解一個前提:要在平臺支持的開發(fā)環(huán)境基礎(chǔ)上遷移項目。
-
Custom Runtime就是在平臺的基礎(chǔ)上,自定義運行環(huán)境。 -
Custom Runtime的本質(zhì)是HTTP Server。
那如何創(chuàng)建Custom Runtime?
- 搭建一個監(jiān)聽
9000固定端口的HTTP Server// 部署靜態(tài)頁面為例 var Koa = require('koa'); var path = require('path'); var htmlRender = require('koa-html-render'); var app = new Koa(); var port = 9000; app.use(htmlRender()); app.use(async (ctx) => { await ctx.html(path.resolve(__dirname, ctx.path)); }) app.listen(process.env.PORT || port, () => { console.log(`----koa is running on ${process.env.PORT || port}=====`) }) - 將啟動Server的命令保存在一個名為
bootstrap的文件// 創(chuàng)建bootstrap文件 #!/usr/bin/env bash export PORT=9000 node app.js -
fun deploy -y將項目部署到函數(shù)計算上 - 可以通過臨時鏈接訪問該靜態(tài)項目
由此,我們可以看到bootstrap文件是HTTP Server的啟動文件。
template.yml對應(yīng)我們服務(wù)列表、函數(shù)列表的配置項。
Koa應(yīng)用的遷移
上述例子,是靜態(tài)頁面的遷移,也可以看作是Koa應(yīng)用的遷移。
連接MongoDB示例
這里,開通了阿里云MongoDB的服務(wù),代碼示例鏈接數(shù)據(jù)庫,將testColl文檔數(shù)據(jù)導(dǎo)出。
這個示例需要注意依賴版本require('mongodb'),mongodb的版本需要是2.2.*。
var uuid = require('node-uuid');
var sprintf = require("sprintf-js").sprintf;
var mongoClient = require('mongodb').MongoClient;
var host = "dds-****-pub.mongodb.rds.aliyuncs.com";
var port = 3717;
var username = "user***";
var password = "***";
var demoDb = "sls";
var demoColl = "testColl";
// 官方建議使用的方案
var url = sprintf("mongodb://%s:%d/%s", host, port, demoDb);
console.info("url:", url);
var conn;
exports.initializer = async function (context, callback) {
// 獲取mongoClient
await mongoClient.connect(url, function(err, db) {
if(err) {
console.error("connect err:", err);
return 1;
}
// 授權(quán). 這里的username基于admin數(shù)據(jù)庫授權(quán)
var adminDb = db.admin();
adminDb.authenticate(username, password, function(err, result) {
if(err) {
console.error("authenticate err:", err);
return 1;
}
conn = db;
// 取得Collecton句柄
conn.db(demoDb)
callback(null, '')
});
});
}
exports.handler = function (event, context, callback) {
var collection = conn.collection(demoColl);
collection.find({}).toArray(function(err, docs) {
console.log("Found the following records");
console.log(docs)
callback(null, docs);
});
}
總結(jié)
應(yīng)用場景
- 長尾應(yīng)用
- 大規(guī)模批處理任務(wù)
- 彈性伸縮
- 基于事件驅(qū)動架構(gòu)的應(yīng)用
- 事件驅(qū)動
- 運維自動化
- 觸發(fā)器
局限
- 用戶對底層計算資源沒有可控性
- 由于目前技術(shù)的成熟度,
Serverless領(lǐng)域尚沒有形成行業(yè)標(biāo)準(zhǔn),意味著用戶將一個平臺上的Serverless應(yīng)用移植到另一個平臺時付出的成本較高
前端學(xué)習(xí)Serverless的出發(fā)點
- 打破潛意識技術(shù)邊界
- 調(diào)優(yōu)行業(yè)內(nèi)的開發(fā)崗位分層結(jié)構(gòu)
- Serverless補足了前端工程師的現(xiàn)有能力,前端與Serverless結(jié)合,是對前端的訴求從頁面開發(fā)向開發(fā)交付整個應(yīng)用轉(zhuǎn)變
- 享受云服務(wù)紅利
- 零運維
- Node.js + Serverless,向全棧進發(fā)
- 云開發(fā)者的切入點
- 熟悉云開發(fā)模式與思想
- 文件:
boostrap、template.yml分別是什么 - 調(diào)試:查看請求參數(shù)的結(jié)構(gòu)
- 示例:幾分鐘部署上線
- 概念:HTTP觸發(fā)器