服务端的 WebAssembly 与 Rust 入门篇

时间:2022-07-25
本文章向大家介绍服务端的 WebAssembly 与 Rust 入门篇,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

随着 WebAssembly 在客户端的发展,WebAssembly 也正在从客户端发展到服务端,这与当年Java 的发展路径非常相似。

一句话形容,WebAssembly 在服务端的优势是提供了接近了原生代码的性能,但是又不损失安全性。

Rust 连续6年在 Stack Overflow 被评为最受欢迎的编程语言之一。同样用一句话形容Rust,提供了与 C/C++ 相媲美的性能,但是又防止了 C 语言中常见的漏洞出现。

WebAssembly 有很多非常好的用例,尤其是在AI,区块链和大数据应用方面。这次以一个 Hello world 为例,来先看看服务端的WebAssembly 和 Rust 是怎么工作的。

这篇文章将展示如何用 Rust 编写的 WebAssembly 函数合并到服务器上的 Node.js 应用程序中。这种方法结合了Rust 的性能,WebAssembly 的安全性和可移植性以及 JavaScript 的易用性。一个典型的应用程序是这样工作的。

  • 主机应用程序是用 JavaScript 编写的 Node.js Web 应用程序,调用 WebAssembly 函数。
  • WebAssembly 字节码程序是用 Rust 编写的。它在 SSVM 中运行,并从 Node.js Web 应用程序中调用。

前提条件:

要使用 Rust 和 WebAssembly 设置高性能 Node.js 环境,需要安装以下内容:

Docker

最简单的入门方法是使用 Docker 构建开发环境。 clone 这个模板项目,然后运行以下 Docker 命令。

# Get the code
$ git clone https://github.com/second-state/ssvm-nodejs-starter
$ cd ssvm-nodejs-starter

# Run Docker container
$ docker build -t ssvm-nodejs:v1 .
$ docker run -p 3000:3000 --rm -it -v $(pwd):/app ssvm-nodejs:v1
(docker) $ cd /app

现在可以编译并运行代码了。

不使用 Docker,手工操作

SSVM 依赖于最新版本的 libstdc ++。 Ubuntu 20.04 LTS已经拥有最新的库。如果您运行的 Linux 版本比较旧,可以选择这几种方式进行升级。

使用下面的命令来安装完整设置:

# Install Rust
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ source $HOME/.cargo/env

# Install Node.js
$ curl -sL https://deb.nodesource.com/setup_14.x |  bash
$ apt-get install -y nodejs

# Install ssvmup toolchain
$ npm install -g ssvmup # Append --unsafe-perm if permission denied

# OS dependencies for SSVM
$ sudo apt-get update
$ sudo apt-get -y upgrade
$ sudo apt install build-essential curl wget git vim libboost-all-dev

# Install the nodejs addon for SSVM
$ npm install ssvm

接下来,clone 模板的 GitHub repo

$ git clone https://github.com/second-state/ssvm-nodejs-starter
$ cd ssvm-nodejs-starter

Hello World

Hello World 这个简单的应用展示了应用程序的各个部分是如何组合在一起的。

Rust 中的 WebAssembly 函数

在这个示例中,Rust 程序将输入的字符串放到 hello 之后。下面是 Rust 程序的内容,放在 src/lib.rs 文件里。我们可以在这个文件中定义多个外部函数。通过 WebAssembly /SSVM,主机 JavaScript 应用可以调用所有 Rust 函数。只需记住用#[wasm_bindgen]注释每个函数。加过注释后, ssvmup 在构建 Rust 函数时,知道生成正确的 JavaScript 到 Rust 接口。

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn say(s: String) -> String {
  let r = String::from("hello ");
  return r + &s;
}

接下来,将 Rust 源代码编译为 WebAssembly 字节码,并为 Node.js 主机环境生成随附的 JavaScript 模块。

$ ssvmup build

生成的文件保存在 pkg/ 目录, .wasm 文件是 WebAssembly 字节码程序,.js文件用于JavaScript模块。

Node.js 主机应用程序

接下来,来到 node 文件夹并检查 JavaScript 程序 app.js。通过自动生成的 ssvm_nodejs_starter_lib.js 模块,编写 JavaScript 调用 WebAssembly 函数变得很容易。下面的代码是 node 应用程序 app.js。node 应用程序只是从生成的模块中导入 say() 函数。node 应用程序从传入的 HTTP GET 请求中获取 name 参数,并以“ hello name”进行响应。

const { say } = require('../pkg/ssvm_nodejs_starter_lib.js');

const http = require('http');
const url = require('url');
const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  const queryObject = url.parse(req.url,true).query;
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end(say(queryObject['name']));
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

如下所示,启动 Node.js 应用程序服务器。

$ node node/app.js
Server running at http://127.0.0.1:3000/

然后从另一个终端窗口进行测试。

$ curl http://127.0.0.1:3000/?name=Wasm
hello Wasm

到这里,一个简单的 Hello World 就完成了!现在你已经完成了入门教程,欢迎继续探索。