WebAssembly 是一種新的W3C規範,無需插件能夠在全部現代瀏覽器中實現近乎原生代碼的性能。同時因爲 WebAssembly 運行在輕量級的沙箱虛擬機上,在安全、可移植性上比原生進程更加具有優點。同時資源消耗小、啓動速度快的特色也很是適合Serverless的場景。開發者們開始探索WebAssembly在Serverless的應用場景。html
WebAssembly (WASM) 是一種能夠在Web瀏覽器上運行的編譯語言(如C/C++, Rust, Go)的技術方案。WebAssembly採用二進制字節碼格式,運行在基於堆棧的虛擬機上。2017年2月28日,四大主流瀏覽器Chrome, Firefox, Safari和IE共同宣佈 WebAssembly 的最小可行產品(MVP)已經完成。node
相比JavaScript, 使用WebAssembly能夠更高效地在Web瀏覽器中運行代碼邏輯。git
WebAssembly做爲社區標準,具備良好的可移植性。WebAssembly代碼邏輯能夠一致地運行在不一樣瀏覽器實現中,並與JavaScript或瀏覽器對象進行交互調用。WebAssembly也能夠運行在非瀏覽器環境下。此外WebAssembly運行在一個沙箱化的執行環境中,嚴格遵照瀏覽器安全策略,具備良好的安全性。github
Function as a Service(FaaS)是Serverless Computing的重要計算形態,它提供了事件驅動的編程模型,開發者只需編寫和上傳事件響應代碼,而平臺則會負責計算資源的彈性伸縮。web
FaaS主要支持了 Node.js, Python, PHP等解釋型語言,也支持Java, C#等編譯型語言。因爲在Node.js 8.0版本之後已經內置了WebAssembly運行時,在主流的FaaS環境能夠經過Node.js實現調用WebAssembly模塊的能力,好比在AWS Lambda和Cloudflare Worker。npm
在FaaS中利用Node.js調用WebAssembly 模塊,有如下優勢編程
咱們也將作一個小實驗,結合Rust和AssemblyScript兩種語言在阿里雲函數計算(FunctionCompute, FC)場景中體驗WebAssembly。瀏覽器
git clone https://github.com/denverdino/fun-wasm
Rust是Mozilla的一個新的系統級編程語言。Mozilla同時也是WebAssembly技術最重要的推進者,它基於WebAssembly發佈了wasm-bindgen,目的提高 JavaScript 和 Rust 之間的互操做性,可讓 Rust代碼可以與JavaScript一塊兒使用。安全
本節參考了Scott Logic的文章,咱們將利用wasm-bindgen,在FunctionCompute的Node.js運行時中運行基於Rust編譯的WebAssembly代碼。網絡
$ cd rust-wasm # 一個簡單的Rust Hello World應用,利用wasm_bindgen聲明與JavaScript代碼的綁定 $ cat src/lib.rs use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn hello_world() -> String { let mut string = String::new(); string.push_str("Hello, rust-wasm!"); return string; } # 編譯生成WebAssembly和NodeJS綁定 $ wasm-pack build --target nodejs # 簡單的函數計算事件響應代碼,在NodeJS中調用WebAssembly邏輯 $ cat index.js const wasm = require("./pkg/rust_wasm"); var getRawBody = require('raw-body') module.exports.handler = function (request, response, context) { // get request body getRawBody(request, function (err, body) { response.setStatusCode(200); response.send(wasm.hello_world()); }); } # Serverless應用部署模板,利用HTTP Trigger進行訪問 $ cat template.yml ROSTemplateFormatVersion: '2015-09-01' Transform: 'Aliyun::Serverless-2018-04-03' Resources: fun: Type: 'Aliyun::Serverless::Service' rust-wasm: Type: 'Aliyun::Serverless::Function' Properties: Handler: index.handler CodeUri: ./ Description: 'http trigger demo!' Runtime: nodejs8 Events: http-test: Type: HTTP Properties: AuthType: ANONYMOUS Methods: ['GET', 'POST', 'PUT']
部署並測試
$ fun deploy ... Waiting for service fun to be deployed... Waiting for function rust-wasm to be deployed... Waiting for packaging function rust-wasm code... package function rust-wasm code done, the number of files you have packaged is:11 Waiting for HTTP trigger http-test to be deployed... methods: [ 'GET', 'POST', 'PUT' ] url: https://xxxxxxx.cn-shanghai.fc.aliyuncs.com/2016-08-15/proxy/fun/rust-wasm/ function http-test deploy success function rust-wasm deploy success service fun deploy success $ curl https://xxxxxxx.cn-shanghai.fc.aliyuncs.com/2016-08-15/proxy/fun/rust-wasm/ Hello, rust-wasm!
AssemblyScript能夠將一個 TypeScript 嚴格的子集編譯成 WebAssembly。AssemblyScript 使用與 TypeScript 相同的語法,但使用了本身的標準庫來支撐 WebAssembly 的功能,這意味着開發者沒必要爲了編寫 WebAssembly 而去學習新的編程語言,這是一個巨大的優勢。並且AssemblyScript是針對WebAssembly設計的語言,它能夠生成更加簡練的WebAssembly代碼,並更加簡單地與JavaScript集成交互。
$ cd assemblyscript # 下面是一個簡單的Fibonacci數列的遞歸實現 $ cat assembly/index.ts // The entry file of your WebAssembly module. export function fib(n: i32): i32 { let t: i32; let a: i32 = 0; let b: i32 = 1; for (let i: i32 = 0; i < n; i++) { t = a + b; a = b; b = t; } return b; } # 生成WebAsssembly目標代碼 $ npm run asbuild # 以下是AssemblyScript本身生成的膠水代碼,用於加載WebAssembly模塊 $ cat wasm.js const fs = require("fs"); const compiled = new WebAssembly.Module(fs.readFileSync(__dirname + "/build/optimized.wasm")); const imports = { env: { abort(_msg, _file, line, column) { console.error("abort called at index.ts:" + line + ":" + column); } } }; Object.defineProperty(module, "exports", { get: () => new WebAssembly.Instance(compiled, imports).exports }); # 事件響應代碼,在NodeJS中調用WebAssembly邏輯,根據query string輸入參數計算Fibonacci結果 $ cat index.js const { fib } = require('./wasm'); var getRawBody = require('raw-body') module.exports.handler = function (request, response, context) { // get request body getRawBody(request, function (err, body) { let strValue = request.queries.n let n = 10 // Default value if (strValue) { n = parseInt(strValue) } response.setStatusCode(200); result = fib(n) response.send(result.toString()); }); }; # Serverless應用部署模板,利用HTTP Trigger進行訪問 $ cat template.yml ROSTemplateFormatVersion: '2015-09-01' Transform: 'Aliyun::Serverless-2018-04-03' Resources: fun: Type: 'Aliyun::Serverless::Service' assemblyscript: Type: 'Aliyun::Serverless::Function' Properties: Handler: index.handler CodeUri: ./ Description: 'http trigger demo!' Runtime: nodejs8 Events: http-test: Type: HTTP Properties: AuthType: ANONYMOUS Methods: ['GET', 'POST', 'PUT']
部署並測試
$ fun deploy ... Waiting for service fun to be deployed... Waiting for function assemblyscript to be deployed... Waiting for packaging function assemblyscript code... package function assemblyscript code done, the number of files you have packaged is:1040 Waiting for HTTP trigger http-test to be deployed... methods: [ 'GET', 'POST', 'PUT' ] url: https://xxxxxx.cn-shanghai.fc.aliyuncs.com/2016-08-15/proxy/fun/assemblyscript/ function http-test deploy success function assemblyscript deploy success service fun deploy success $ curl https://xxxxxx.cn-shanghai.fc.aliyuncs.com/2016-08-15/proxy/fun/assemblyscript/\?n\=10 89 $ curl https://xxxxxx.cn-shanghai.fc.aliyuncs.com/2016-08-15/proxy/fun/assemblyscript/\?n\=40 165580141
WebAssembly仍是一個很是年輕的技術,大量的功能有待完善,可是它已經展示出巨大的潛力,逐漸在非Web領域獲得應用,如區塊鏈的智能合約實現。Mozilla在19年3月推出了一個標準化的 WebAssembly System Interface(WebAssembly系統接口,簡稱 WASI),來定義WASM與系統資源的交互,好比文件系統訪問,內存管理,網絡鏈接等。軟件開發商能夠針對具體的操做系統和運行環境提供不一樣的接口實現。它的目標是在不一樣設備和操做系統上運行相同的 WebAssembly 代碼,這與Java 提出的 「build once run anywhere」 目標有些相似,可是WebAssembly + WASI徹底基於開放生態,並提供更好的可移植性和安全性。
將來隨着WebAssembly自身技術和工具鏈的成熟,WebAssembly將有機會成爲一個跨語言、跨平臺的Serverless runtime,進一步推進雲原生應用的進化。社區也開始在相關領域進行探索,好比Fastly公司爲其邊緣計算平臺推出 Lucet 項目,它針對Serverless場景提供了優化的WebAssembly編譯器和運行時,能夠將實例化 WebAssembly 模塊的時間下降到數十微妙,內存開銷下降到只需幾KB。
WebAssembly和WASI等技術遠非完美,它們還在快速迭代演進中,期待它給咱們帶來更多驚喜。
本文爲雲棲社區原創內容,未經容許不得轉載。