服务端的 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 环境,需要安装以下内容:
- 现代 Linux 发行版,例如Ubuntu Server 20.04 TLS
- Rust 语言
- Node.js
- Second State 虚拟机(SSVM)
- ssvmup 编译器工具链
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 就完成了!现在你已经完成了入门教程,欢迎继续探索。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- js字符串/数组常用方法总结
- ThinkPHP5+mpdf 实现富文本生成 PDF文件
- nodejs使用readline逐行读取和写入文件
- go语言逐行读取和写入文件
- SpringBoot中Tomcat是如何启动的
- 自定义注解详解及应用
- 微服务开源框架TARS 之 框架服务解析
- dotnet 在 UOS 国产系统上使用 Xamarin Forms 创建 xaml 界面的 GTK 应用
- K8s集群上使用Helm部署2.4.6版本Rancher集群
- VMware下安装CentOS
- leetcode多线程之按序打印
- 表格的实现
- 使用 Node.js 定制你的技术雷达:中篇
- 数据库PostrageSQL-在Windows上从源代码安装
- Redis的过期策略和内存淘汰策略及LRU算法详解