上次談到了如何搭建本身的faas?,被同行評論有些標題黨,這篇文章將接着上文,來介紹一些乾貨。同時在寫這篇文章的時候,核心功能vmbox已經開源,歡迎你們點贊fork。javascript
faas
是雲廠商提出的一種函數即服務
的程序部署模式,以函數爲核心,實現以函數粒度的服務伸縮,這項技術很是複雜,有不少的技術資料,你們能夠查看雲廠商的文檔。咱們這裏聊到的是比較簡單的實現方式,以傳統服務爲基礎,借用nodejs的沙盒能力,實現安全執行用戶的函數,達到函數即服務的目的。前端
相信你們項目中都會遇到多個項目使用同一個函數
,該函數具備規則複雜
、邏輯獨立
等特色的純函數,前端每每是發佈一個npm包,直接引入,粗暴點的直接複製到另外一個項目中。假設校驗身份證件號的真僞等函數,有時後端也須要用,因爲語言的差別,直接複用不太可能,將這類函數抽象成爲單獨的函數的想法便應運而生,決定嘗試最前沿的編程思想(前端的世界就是瘋狂試探),自建faas工程就這樣開始了。java
將js函數轉化爲API服務,即實現函數即服務
node
實現上述目標的核心難題是js函數的安全執行環境,上一期已經談到node的沙盒存在的問題,這裏再也不贅述。具體的解決方案,已經開源,你們能夠點擊查看vmbox。對源碼感興趣的同窗能夠對照上篇文章中的流程圖查看代碼,歡迎貢獻。git
迴歸正題,vmbox
是通過真實項目檢驗的node沙盒庫,具備六大特色github
vmbox的實例只有一個run
方法,返回值是一個promise
,接收三個參數數據庫
參數名 | 類型 | 是否選填 | 默認值 | 簡介 |
---|---|---|---|---|
code | string | 必填 | - | 運行的js代碼 |
context | object | 選填 | {} | 函數運行上下文 |
stack | boolean | 選填 | false | 函數內調用其餘函數,記錄函數調用棧 |
若是代碼運行出錯,會使用Promise.reject(error)拋出異常,須要對異常進行捕獲npm
基本用法編程
const VMBox = require('vmbox');
const vmBox = new VMBox({
timeout: 100,
asyncTimeout: 500
});
const context = {
sum(a, b){
return a + b;
}
}
const fn = `sum(2, 3)`
vmBox.run(fn).then(console.log)
// 打印5
複製代碼
高級用法後端
藉助函數運行上下文,能夠作不少事情,下面實現了一個從函數內部調用其餘函數的方法。
const VMBox = require('vmbox');
const vmBox = new VMBox({
timeout: 100,
asyncTimeout: 500
});
const fnGroup = {
sum: `async function main({params, fn}){ const {a, b} = params; return a + b }`,
caller: `async function main({params, fn}){ return await fn.call('sum', params); }`
};
async function run(code, context, stack = false) {
const runCode = code + `;\n(async () => { return await main({params, fn}); })()`
return vmBox.run(runCode, context, stack);
}
const fn = {
call: (name, params) => {
const code = fnGroup[name];
if (code) {
return run(code, { params, fn }, true);
} else {
return null;
}
}
}
const context = {
fn,
params: {
a: 10,
b: 20
}
}
const code = fnGroup.caller;
try {
const res = await run(code, context);
console.log(res); // 打印30
} catch (error) {
console.log(error);
}
複製代碼
vm2
中異步死循環的問題,可是進程啓動的成本比較高,所以在使用過程當中儘可能避免進程的重啓,提升運行效率。