webservice服务的优点和缺点,webservice接口的优缺点

首页 > 经验 > 作者:YD1662022-11-14 19:53:36

本文翻译自 https://blog.logrocket.com/rust-microservices-server-side-webassembly/。在 reddit 获超200赞。

webservice服务的优点和缺点,webservice接口的优缺点(1)

过去几年中,Rust 编程语言已获得主流采用。它一直被开发者评为最受欢迎的编程语言[1],并已被Linux内核接受[2]。 Rust 使开发者能够编写正确且内存安全的程序,这些程序与 C 程序一样速度快,占用空间小。它非常适合需要高可靠性和高性能的基础架构软件,包括服务端应用程序[3]

然而,对于服务端应用程序,Rust 也提出了一些挑战。Rust 程序被编译成原生机器代码,在多租户云环境中不可移植且不安全。我们还缺乏在云中管理和编排原生应用程序的工具。

因此,服务端 Rust 应用程序通常在 VM 或 Linux 容器中运行,这会带来大量的内存和 CPU 开销。这削弱了 Rust 在效率方面的优势,并且难以在资源受限的环境中部署服务,例如边缘数据中心和边缘云。这个问题的解决方案是 WebAssembly[4] (Wasm)。

Wasm 最初是作为 Web 浏览器中的安全运行时,Wasm 程序可以安全地隔离在自己的沙箱中。借助新一代的 Wasm 运行时,例如 Cloud Native Computing Foundation 的 WasmEdge Runtime[5],你现在可以在服务器上运行 Wasm 应用程序。可以将 Rust 程序编译为 Wasm 字节码,然后将 Wasm 应用程序部署到云端。

根据发表在 IEEE Software 上的研究[6],与 Linux 容器中原生编译的 Rust 应用相比,Wasm 应用可以快 100 倍(尤其是在启动时)且大小仅为 1/100。因而特别适合边缘云等资源受限的环境。

Wasm 运行时沙箱的攻击面要小得多,并且比 Linux 容器提供了更好的隔离。此外,Wasm 运行时可跨操作系统和硬件平台移植。一旦将 Rust 程序编译到 Wasm 中,就可以在从开发到生产、从云到边缘的任何地方运行。

webservice服务的优点和缺点,webservice接口的优缺点(2)

WebAssembly 沙箱中 Rust 微服务的拆解

本文中,我们将介绍在 Rust 中构建微服务所需的工具、库、API、框架和技术。我们还将演示如何在 WasmEdge WebAssembly Runtime 中部署、运行和扩展这些微服务。

准备事项

继续阅读本文,需具备以下条件:

创建 Web 服务

微服务首先是一个 Web 服务器。WasmEdge Runtime 支持异步和 non-blocking network socket。你可以用 Rust 编写 networking 应用程序,将它们编译成 Wasm,然后在 WasmEdge Runtime 中运行它们。在 Rust 生态系统中,WasmEdge 支持以下内容:

下面的示例来自 microservice-rust-mysql[16] demo app,展示了如何为 WasmEdge 在 hyper[17] 创建一个 Web 服务器 。Web 服务器的主要监听循环如下:

let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); let make_svc = make_service_fn(|_| { let pool = pool.clone(); async move { Ok::<_, Infallible>(service_fn(move |req| { let pool = pool.clone(); handle_Request(req, pool) })) } }); let server = Server::bind(&addr).serve(make_svc); if let Err(e) = server.await { eprintln!("server error: {}", e); } Ok(())

一旦请求进入,事件处理程序 handle_request(), 将被异步调用,以便它可以处理多个并发请求。它根据请求方法和路径生成响应:

async fn handle_request(req: Request<Body>, pool: Pool) -> Result<Response<Body>, anyhow::Error> { match (req.method(), req.uri().path()) { (&Method::GET, "/") => Ok(Response::new(Body::from( "... ...", ))), // Simply echo the body back to the client. (&Method::POST, "/echo") => Ok(Response::new(req.into_body())), (&Method::GET, "/init") => { let mut conn = pool.get_conn().await.unwrap(); "DROP TABLE IF EXISTS orders;".ignore(&mut conn).await?; "CREATE TABLE orders (order_id INT, product_id INT, quantity INT, amount FLOAT, shipping FLOAT, tax FLOAT, shipping_address VARCHAR(20));".ignore(&mut conn).await?; drop(conn); Ok(Response::new(Body::from("{\"status\":true}"))) } (&Method::POST, "/create_order") => { // ... ... } // Return the 404 Not Found for other routes. _ => { let mut not_found = Response::default(); *not_found.status_mut() = StatusCode::NOT_FOUND; Ok(not_found) } } }

现在我们有了一个用于 Web 服务的 HTTP 服务器。

创建 Web 服务客户端

一个典型的 Web 服务还需要使用其他 Web 服务。通过 tokio 和/或 mio crates,WasmEdge 应用程序可以轻松地为 Web 服务合并 HTTP 客户端。WasmEdge 支持以下 Rust crate:

以下示例展示了如何从微服务对 Web 服务 API 进行 HTTP POST:

let client = reqwest::Client::new(); let res = client .post("http://eu.httpbin.org/post") .body("msg=WasmEdge") .send() .await?; let body = res.text().await?; println!("POST: {}", body); 创建数据库客户端

大多数微服务都由数据库支持。WasmEdge 支持以下 MySQL 驱动程序的 Rust crates:

下面的例子显示了如何将一组记录插入到数据库表中:

let orders = vec![ Order::new(1, 12, 2, 56.0, 15.0, 2.0, String::from("Mataderos 2312")), Order::new(2, 15, 3, 256.0, 30.0, 16.0, String::from("1234 NW Bobcat")), Order::new(3, 11, 5, 536.0, 50.0, 24.0, String::from("20 Havelock")), Order::new(4, 8, 8, 126.0, 20.0, 12.0, String::from("224 Pandan Loop")), Order::new(5, 24, 1, 46.0, 10.0, 2.0, String::from("No.10 Jalan Besar")), ]; r"INSERT INTO orders (order_id, production_id, quantity, amount, shipping, tax, shipping_address) VALUES (:order_id, :production_id, :quantity, :amount, :shipping, :tax, :shipping_address)" .with(orders.iter().map(|order| { params! { "order_id" => order.order_id, "production_id" => order.production_id, "quantity" => order.quantity, "amount" => order.amount, "shipping" => order.shipping, "tax" => order.tax, "shipping_address" => &order.shipping_address, } })) .batch(&mut conn) .await?;

下面的例子显示了如何查询数据库表并返回一组记录集合:

let loaded_orders = "SELECT * FROM orders" .with(()) .map( &mut conn, |(order_id, production_id, quantity, amount, shipping, tax, shipping_address)| { Order::new( order_id, production_id, quantity, amount, shipping, tax, shipping_address, ) }, ) .await?; dbg!(loaded_orders.len()); dbg!(loaded_orders); 构建、部署和运行微服务

microservice-rust-mysql[22] 项目提供了一个数据库驱动的微服务的完整例子。让我们以它为例,来构建、部署和运行该服务。

docker CLI 和 Docker Desktop 为 WasmEdge 应用程序开发提供无缝支持。在项目 repo 的根目录中,你只需要一个命令来构建和启动微服务的所有组件(即 WasmEdge 应用程序和 mariaDB[23] 数据库服务器) :

docker compose up

然后,可以使用 curl 通过微服务测试数据库上的 CRUD 操作。或者,你可以:

以下命令在 Linux 系统上安装上述准备事项:

// Install Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh // Install WasmEdge curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -e all // Install MySQL. It is available as a package in most Linux distros sudo apt-get update sudo apt-get -y install mysql-server libmysqlclient-dev sudo service mysql start

接下来,将微服务应用程序构建成 Wasm 字节码:

cargo build --target wasm32-wasi --release

然后在 WasmEdge Runtime 中启动微服务:

wasmedge --env "DATABASE_URL=mysql://user:passwd@127.0.0.1:3306/mysql" order_demo_service.wasm

然后,可以使用微服务的 Web API 访问数据库:

// Init the database table curl http://localhost:8080/init // Insert a set of records curl http://localhost:8080/create_orders -X POST -d @orders.json // Query the records from the database curl http://localhost:8080/orders // Update the records curl http://localhost:8080/update_order -X POST -d @update_order.json // Delete a record by its id curl http://localhost:8080/delete_order?id=2 进入生产

到目前为止,我们已经看到了一个完整的数据库驱动的微服务。然而,在现实世界中,一家公司可能拥有数百个微服务。它们必须由 Kubernetes 等云原生框架进行管理和编排。

WasmEdge 应用程序完全符合 OCI[27] 标准。它们可以在 Docker Hub 或其他 Open Container Initiative 存储库中进行管理和存储。通过 crun 集成[28],WasmEdge 可以在同一个 Kubernetes 集群中与 Linux 容器应用程序并行运行。这个存储库展示了如何在流行的容器工具链中运行 WasmEdge 应用程序,包括 CRI-O、containerd、Kubernetes、Kind、OpenYurt、KubeEdge 等。

webservice服务的优点和缺点,webservice接口的优缺点(3)

Kubernetes 堆栈中的 WebAssembly 运行时

此外,微服务通常与服务框架一起部署。例如,Dapr[29] 是一个流行的微服务运行时框架。它为每个微服务提供一个“sidecar”服务。微服务通过 Dapr API 访问 Sidecar,以发现和调用网络上的其他服务、管理状态数据和访问消息队列。WASI(WebAssembly 系统接口)的 Dapr SDK[30] 使基于 WasmEdge 的微服务能够访问其附加的 Dapr sidecar。我们也提供了 一个完整的演示应用程序[31],这个 demo 有一个 Jamstack 静态 Web 前端、三个微服务和一个数据库服务。

结论

本文中,我们讨论了为什么 WebAssembly 是基于 Rust 的服务端应用程序的出色运行时沙盒格式。我们通过具体的代码示例演示了如何创建 HTTP Web 服务、使用其他 Web 服务、从 Rust 访问关系数据库,然后在 WasmEdge 中运行已编译的应用程序。我们还谈到了部署问题,例如 Kubernetes 和 Dapr 集成。

使用这些 crate 和模板应用程序,你将能够在 Rust 中构建自己的轻量级微服务!除了微服务之外,WasmEdge Runtime 还可以在许多不同的场景中广泛用作应用程序沙箱:

了解有关 WasmEdge 的更多信息,请参阅官方文档[37]

参考资料

[1]

评为最受欢迎的编程语言: https://survey.stackoverflow.co/2022/

[2]

被Linux内核接受: https://thenewstack.io/rust-in-the-linux-kernel/

[3]

包括服务端应用程序: https://blog.logrocket.com/template-rendering-in-rust/

[4]

WebAssembly: https://webassembly.org/

[5]

WasmEdge Runtime: https://github.com/WasmEdge/WasmEdge

[6]

发表在 IEEE Software 上的研究: https://arxiv.org/abs/2010.07115

[7]

准备工作: https://blog.logrocket.com/rust-microservices-server-side-webassembly/#prerequisites

[8]

创建 Web 服务: https://blog.logrocket.com/rust-microservices-server-side-webassembly/#creating-a-web-service

[9]

创建 Web 服务客户端: https://blog.logrocket.com/rust-microservices-server-side-webassembly/#creating-a-web-service-client

[10]

创建数据库客户端: https://blog.logrocket.com/rust-microservices-server-side-webassembly/#creating-a-database-client

[11]

构建、运行和部署微服务: https://blog.logrocket.com/rust-microservices-server-side-webassembly/#building-running-and-deploying-the-microservice

[12]

进入生产: https://blog.logrocket.com/rust-microservices-server-side-webassembly/#going-to-production

[13]

tokio: https://github.com/WasmEdge/tokio

[14]

mio: https://github.com/WasmEdge/mio

[15]

hyper: https://github.com/WasmEdge/hyper

[16]

microservice-rust-mysql: https://github.com/second-state/microservice-rust-mysql

[17]

hyper: https://hyper.rs/

[18]

reqwest: https://github.com/WasmEdge/reqwest

[19]

http_req: https://github.com/second-state/http_req

[20]

myql: https://github.com/WasmEdge/rust-mysql-simple-wasi

[21]

mysql_async: https://github.com/WasmEdge/mysql_async_wasi

[22]

microservice-rust-mysql: https://github.com/second-state/microservice-rust-mysql

[23]

mariaDB: https://mariadb.org/

[24]

安装 Rust 编译器: https://www.rust-lang.org/tools/install

[25]

安装 WasmEdge Runtime: https://wasmedge.org/book/en/quick_start/install.html

[26]

安装 MySQL 数据库服务器: https://dev.mysql.com/doc/mysql-getting-started/en/

[27]

OCI: https://opencontainers.org/

[28]

crun 集成: https://opensource.com/article/22/10/wasm-containers

[29]

Dapr: https://dapr.io/

[30]

Dapr SDK: https://github.com/second-state/dapr-sdk-wasi

[31]

一个完整的演示应用程序: https://github.com/second-state/dapr-wasm

[32]

flows.network: https://flows.network/

[33]

用户定义函数: https://www.secondstate.io/articles/udf-saas-extension/

[34]

Android: https://wasmedge.org/book/en/contribute/build_from_src/android.html

[35]

seL4: https://www.secondstate.io/articles/wasmedge-sel4/

[36]

Ewasm: https://ewasm.readthedocs.io/en/mkdocs/

[37]

官方文档: https://wasmedge.org/book/en/

WasmEdge将于11月9日在硅谷举办Wasm Meetup,戳此报名和来自Docker、Dapr、字节等的技术大佬交流

https://www.meetup.com/sf-software-development-meetup-group/events/289224769/

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.