专业编程基础技术教程

网站首页 > 基础教程 正文

用 WasmEdge 和 Rust 在边缘云上构建高性能且安全的微服务

ccvgpt 2024-11-25 10:14:51 基础教程 1 ℃

本文为英文译文,原文首发在 FreeCodeCamp 原文链接:https://www.freecodecamp.org/news/edge-cloud-microservices-with-wasmedge-and-rust/

边缘云让开发者能够在靠近用户的地方部署微服务(即细颗粒度的 Web 服务),从而实现更好的用户体验(即非常快的响应时间)、绝佳的安全性以及高可用性。 边缘云利用本地乃至私有的数据中心、CDN 网络和电信数据中心(例如 5G MEC)来提供计算服务。 边缘云的成功案例包括 Cloudflare、Fastly、Akamai、fly.io、Vercel、Netlify 等。

用 WasmEdge 和 Rust 在边缘云上构建高性能且安全的微服务

但是,与大型公共云相比,边缘云是一个资源受限的环境。 如果边缘微服务本身运行缓慢、臃肿或不安全,将导致在边缘云上部署的全部优势丧失殆尽。

本文将展示如何创建轻量级和高性能的 Web 服务,然后将其免费部署到边缘云提供商 fly.io[1] 上。

Fly.io[2] 是一个领先的边缘云 VM 服务提供商,它在世界各地都有边缘数据中心。fly.io[3] VM 支持应用程序服务器、数据库以及我们这种微服务的轻量级 runtime。

我将使用 WasmEdge runtime 作为这些微服务的安全沙箱。 WasmEdge 是专门针对云原生服务优化的 WebAssembly runtime。我们将在基于 WasmEdge 的 Docker Images 中打包用 Rust 或 JavaScript 编写的微服务应用程序。这种方法有几种巨大优势。

  • WasmEdge 以接近原生的速度运行沙盒应用。根据一项经过同行评审的研究,WasmEdge 能够以近似 Linux 运行原生机器代码的速度运行 Rust 程序。
  • WasmEdge 是一个高度安全的 runtime。它可以保护你的应用程序免受外部和内部攻击威胁。 WasmEdge runtime 受攻击的脆弱点,相比常规 Linux OS runtime 大大减少。软件供应链攻击的风险大大降低了,因为 WebAssembly 沙箱仅允许明确声明的访问。
  • WasmEdge 在内存足迹上提供了一个完整的可移植应用程序 runtime 环境,仅是标准Linux OS runtime 镜像的1/10。
  • WasmEdge runtime 是跨平台的。这意味着机器的开发和部署不必相同。一旦创建了一个 WasmEdge 应用程序,就可以将其部署到支持 WasmEdge 的任何地方,包括 fly.io[4] 基础设施。

如果是复杂的应用程序,该性能优势会进一步放大。 例如,WasmEdge AI 推理应用程序不需要 Python 安装。WasmEdge node.js 应用程序也无需安装 node.js 和 v8。

本文接下来,我将演示如何运行

  • 异步 HTTP 服务器(Rust)
  • 一个非常快的图片分类 Web 服务(在Rust)和
  • node.js Web服务器
  • 具有数据库连接的有状态的微服务

所有这些都可以在 WasmEdge 中快速且安全地运行,同时只消耗常规 Linux 容器所需资源的1/10。

前期准备

首先,请确保在系统上安装了 Docker 工具。如果没有,请按照本教程的第一节[5]安装 Docker。接下来,我们将使用在线安装程序来安装 WasmEdge、Rust 和 fly.io[6]flyctl工具。

安装 WasmEdge。此处查看详细信息。[7]

curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -e all

安装 Rust。此处查看详细信息。[8]

`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`

fly.io[9] 安装 flyctl 工具。此处查看[10]详细信息[11]

`curl -L `[`https://fly.io/install.sh`](https://fly.io/install.sh "`https://fly.io/install.sh`")` | sh`

安装好了 flyctl 之后, 请按照指引在 fly.io[12].上注册免费帐[13]户。现在就可以在边缘云上部署 Web 服务了!

Rust 写的一个简单的微服务

我们的第一个示例是用 Rust 编写的简单 HTTP 服务。它演示了一个现代的 Web 应用程序,可以扩展以支持任意复杂的业务逻辑。基于流行的 Tokio 和 Hyper Crate,这个微服务是非常快、异步的(non-blocking),并且对于开发者来说非常容易创建。

完全静态链接的 WasmEdge 镜像只有 4MB(相比之下基础 Linux 镜像则为 40MB)。这足以运行用 Rust 的 tokio 和 hyper 框架编写的异步 HTTP 服务。

运行以下两个 CLI 命令,然后从 WasmEdge 的 Slim Docker 镜像创建fly.io[14] 应用。

$ flyctl launch --image juntaoyuan/flyio-echo
$ flyctl deploy

好了!可以使用 curl 命令测试部署的 Web 服务是否成功。 它回显了你发布的任何数据。

$ curl https://proud-sunset-3795.fly.dev/echo -d "Hello WasmEdge on fly.io!"
Hello WasmEdge on fly.io!

juntaoyuan/flyio-echo 镜像的 dockerfile 包含 WasmEdge runtime 和自定义的 Web 应用程序 WasmEdge_hyper_server.wasm 的完整包。

FROM WasmEdge/slim-runtime:0.11.0
ADD WasmEdge_hyper_server.wasm /
CMD ["WasmEdge", "--dir", ".:/", "/WasmEdge_hyper_server.wasm"]

构建 WasmEdge_hyper_server.wasm 应用程序的 Rust 源代码项目在这里。[15]它使用 Tokio API 启动 HTTP 服务器。 当服务器收到请求时,它会委派给 echo()函数以异步处理请求。这允许微服务接受和处理多个并发的 HTTP 请求。

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let addr = SocketAddr::from(([0, 0, 0, 0], 8080));

    let listener = TcpListener::bind(addr).await?;
    println!("Listening on http://{}", addr);
    loop {
        let (stream, _) = listener.accept().await?;

        tokio::task::spawn(async move {
            if let Err(err) = Http::new().serve_connection(stream, service_fn(echo)).await {
                println!("Error serving connection: {:?}", err);
            }
        });
    }
}

异步 echo() 函数如下。它利用 hyper 提供的 HTTP API 来解析请求并生成响应。在这里,响应只是“请求数据正文”。

async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
    match (req.method(), req.uri().path()) {
        ... ...
        (&Method::POST, "/echo") => Ok(Response::new(req.into_body())),
        ... ...

        // Return the 404 Not Found for other routes.
        _ => {
            let mut not_found = Response::default();
            *not_found.status_mut() = StatusCode::NOT_FOUND;
            Ok(not_found)
        }
    }
}

现在让我们在基本的微服务中加点料!

Rust 写的一个 AI 推理微服务

本例中,我们将创建一个用于图片分类的 Web 服务。它通过 Tensorflow Lite 模型处理上传的图片。我们将使用 WasmEdge 的 Rust API 来访问 Tensorflow,而不是创建一个复杂(且臃肿)的 Python 程序,它以本机机器代码速度运行推理任务(例如,如果有 GPU ,也可以在 GPU 硬件上运行)。通过 WASI-NN 标准,WasmEdge 的 Rust API 可以与 Tensorflow、PyTorch、OpenVINO 和其他 AI 框架中的 AI 模型一起使用。

对于包含完整 Tensorflow Lite 依赖项的 AI 推理应用程序,WasmEdge 占用空间小于 115MB。 相比之下,标准 Tensorflow Linux 镜像超过 400MB。

从 WasmEdge + Tensorflow 的 slim Docker 镜像开始,运行以下两个 CLI 命令来创建并部署一个 fly.io[16] 应用程序。

$ flyctl launch --image juntaoyuan/flyio-classify
$ flyctl deploy

好了!你可以使用 curl 命令来测试部署的 Web 服务是否真的有效。它返回带有可能性等级的图片分类结果。

$ curl https://silent-glade-6853.fly.dev/classify -X POST --data-binary "@grace_hopper.jpg"
military uniform is detected with 206/255 confidence

juntaoyuan/flyio-classify Docker 镜像的 Dockerfile 包含 WasmEdge runtime 的完整包、整个 Tensorflow 库及其依赖项,以及自定义 Web 应用程序 WasmEdge_hyper_server_tflite.wasm

FROM WasmEdge/slim-tf:0.11.0
ADD WasmEdge_hyper_server_tflite.wasm /
CMD ["WasmEdge-tensorflow-lite", "--dir", ".:/", "/WasmEdge_hyper_server_tflite.wasm"]

用于构建 WasmEdge_hyper_server_tflite.wasm 应用程序的 Rust 源代码项目在这里[17]。 基于 tokio 的异步 HTTP 服务器位于 async main() 函数中,如上一个示例所示。 classify() 函数处理请求中的图片数据,将图片转换为 tensor,运行 Tensorflow 模型,然后将返回值(在一个 tensor 中)转换为文本标签和所识别出内容的概率。

async fn classify(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
    let model_data: &[u8] = include_bytes!("models/mobilenet_v1_1.0_224/mobilenet_v1_1.0_224_quant.tflite");
    let labels = include_str!("models/mobilenet_v1_1.0_224/labels_mobilenet_quant_v1_224.txt");
    match (req.method(), req.uri().path()) {
        
        (&Method::POST, "/classify") => {
            let buf = hyper::body::to_bytes(req.into_body()).await?;
            let flat_img = WasmEdge_tensorflow_interface::load_jpg_image_to_rgb8(&buf, 224, 224);

            let mut session = WasmEdge_tensorflow_interface::Session::new(&model_data, WasmEdge_tensorflow_interface::ModelType::TensorFlowLite);
            session.add_input("input", &flat_img, &[1, 224, 224, 3])
                .run();
            let res_vec: Vec<u8> = session.get_output("MobilenetV1/Predictions/Reshape_1");
            ... ...
            
            let mut label_lines = labels.lines();
            for _i in 0..max_index {
              label_lines.next();
            }
            let class_name = label_lines.next().unwrap().to_string();

            Ok(Response::new(Body::from(format!("{} is detected with {}/255 confidence", class_name, max_value))))
        }

        // Return the 404 Not Found for other routes.
        _ => {
            let mut not_found = Response::default();
            *not_found.status_mut() = StatusCode::NOT_FOUND;
            Ok(not_found)
        }
    }
}

在本文的最后,我们将讨论如何向 Rust 微服务添加更多功能,例如数据库客户端和 Web 服务客户端。

Node.js 中的一个简单的微服务

虽然基于 Rust 的微服务轻巧快速,但并不是每个人都是 Rust 开发者(目前)。如果更熟悉 JavaScript,你仍然可以充分利用 WasmEdge 在边缘云中的安全性、性能、占用空间小和可移植性!具体来说,可以使用 node.js API 为 WasmEdge 创建微服务!

对于 Node.js 应用程序,WasmEdge 占用空间小于 15MB。相比之下,标准 Node.js Linux 镜像超过 150MB。

从 WasmEdge + node.js 的 slim Docker 镜像开始,运行以下两个 CLI 命令,创建并部署一个 fly.io[18] 应用。

$ flyctl launch --image juntaoyuan/flyio-nodejs-echo
$ flyctl deploy

好了!可以使用 curl 命令来测试部署的 Web 服务是否真的有效。它会回显你发布给它的任何数据。

$ curl https://solitary-snowflake-1159.fly.dev -d "Hello WasmEdge for Node.js on fly.io!"
Hello WasmEdge for Node.js on fly.io!

juntaoyuan/flyio-nodejs-echo Docker 镜像的 Dockerfile 包含 WasmEdge runtime 、QuickJS runtime WasmEdge_quickjs.wasm、node.js 模块的完整包[19]和 Web 服务应用程序 node_echo.js

FROM WasmEdge/slim-runtime:0.11.0
ADD WasmEdge_quickjs.wasm /
ADD node_echo.js /
ADD modules /modules
CMD ["WasmEdge", "--dir", ".:/", "/WasmEdge_quickjs.wasm", "node_echo.js"]

node_echo.js 应用程序的完整 JavaScript 源代码如下。很明显,它仅使用标准 node.js API 来创建一个异步 HTTP 服务器,该服务器回显 HTTP 请求正文。

import { createServer, request, fetch } from 'http';

createServer((req, resp) => {
  req.on('data', (body) => {
    resp.end(body)
  })
}).listen(8080, () => {
  print('listen 8080 ...\n');
})

WasmEdge 的 QuickJS 引擎不仅提供 node.js 支持,还提供 Tensorflow 推理支持。我们将 Rust TensorFlow 和 WASI-NN SDK 封装到 JavaScript API 中,以便 JavaScript 开发者可以轻松创建 AI 推理应用程序[20]

边缘的状态微服务

使用 WasmEdge,还可以创建由数据库支持的有状态微服务。此 GitHub 代码库[21]包含 WasmEdge 应用程序中基于 tokio 的 non-blocking 数据库客户端的示例。

  • MySQL client[22] 允许 WasmEdge 应用程序访问大多数云数据库。
  • WasmEdge 应用程序可以使用anna-rs[23] 作为边缘缓存或者数据库。

现在,快快使用 WasmEdge SDK 和 runtime 在边缘云上构建各种 Web 服务吧。已经迫不及待地想看到你的成果了!

参考资料

[1]

fly.io: http://fly.io/

[2]

Fly.io: http://fly.io/

[3]

fly.io: http://fly.io/

[4]

fly.io: http://fly.io/

[5]

本教程的第一节: https://www.freecodecamp.org/news/the-docker-handbook/

[6]

fly.io: http://fly.io/

[7]

此处查看详细信息。: https://wasmedge.org/book/en/start/install.html

[8]

此处查看详细信息。: https://www.rust-lang.org/tools/install

[9]

fly.io: http://fly.io/

[10]

此处查看: https://fly.io/docs/hands-on/install-flyctl/

[11]

详细信息: https://www.rust-lang.org/tools/install

[12]

fly.io: http://fly.io/

[13]

注册免费帐: https://fly.io/docs/hands-on/sign-up/%EF%BC%89

[14]

fly.io: http://fly.io/

[15]

这里。: https://github.com/wasmedge/wasmedge/wasmedge_hyper_demo/tree/tree/main/main/server%EF%BC%89%E4%B8%8A%E8%8E%B7%E5%BE%97%E3%80%82

[16]

fly.io: http://fly.io/

[17]

这里: https://github.com/WasmEdge/wasmedge_hyper_demo/tree/main/server-tflite

[18]

fly.io: http://fly.io/

[19]

完整包: https://wasmedge.org/book/en/dev/js/nodejs.html#the-javascript-modules

[20]

轻松创建 AI 推理应用程序: https://wasmedge.org/book/en/dev/js/tensorflow.html

[21]

代码库: https://github.com/WasmEdge/wasmedge-db-examples

[22]

MySQL client: https://github.com/WasmEdge/wasmedge-db-examples/tree/main/mysql

[23]

anna-rs: https://github.com/WasmEdge/wasmedge-db-examples/tree/main/anna

Tags:

最近发表
标签列表