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等技术远非完美,它们还在快速迭代演进中,期待它给咱们带来更多惊喜。
本文为云栖社区原创内容,未经容许不得转载。