如何部署 Rust 应用程序?
在 StackOverflow 开发人员调查中,Rust 已连续 4 年成为最受推崇的语言,因为它为采用者提供了多种功能。
Mozilla 创建 Rust 的目的是为了使其可靠、高性能且对开发人员友好。Rust 的语法与 C++ 和 C 等语言相似,其主要目标用户是开发人员。
Rust 还注重内存安全和并发性,其模型避免了使用其他语言的开发人员所面临的相关陷阱。
您将学习如何用 Rust 构建 API,以利用本文的优势。您将通过在Back4app 的免费容器化服务上制作、容器化和部署 Rust 应用程序来学习。
使用Rust的优势
在项目中使用 Rust 有很多好处。以下是其中一些重要优势:
零成本抽象
Rust 在提供高级抽象的同时,不会增加额外的运行时成本。这意味着你在代码中使用的抽象(函数、迭代器或泛型)不会使你的程序变慢。
Rust 编译器会手动优化编译后底层代码的抽象。Rust 弥补了表现力、底层、细粒度控制与性能之间的差距。
实现并发程序内存安全的无畏并发方法
Rust 采用 “无所畏惧的方法 “来处理并发问题,其特点是安全和高效。Rust 的并发模型利用其所有权模型和类型检查来防止编译时出现数据竞赛。
这一功能使您能够编写多线程应用程序,而不会出现共享状态并发的弊端,如死锁和竞赛条件。
先进的类型系统和所有权模式
Rust 的类型系统及其所有权规则是帮助实现内存安全的独特功能。
所有权模型使用借用检查器来确保每条数据都有一个所有者,并管理其生命周期,以防止出现悬挂指针和内存泄漏等问题。
跨平台兼容性和集成性
如果您想构建跨平台应用程序,Rust 是一个不错的选择。您只需编写一次代码,即可在多个平台上编译,无需对现有代码库进行重大修改。
Rust 与其他编程语言(尤其是 C 语言)集成得很好,因此适用于网络汇编和嵌入式系统任务。
使用 Rust 的局限性
在使用 Rust 构建生产级应用程序时,你一定会遇到一些挫折。
其中一些原因可能包括 Rust 的陡峭学习曲线、因内存和其他检查而导致的较长编译时间,以及其全新的小型生态系统。
在使用 Rust 构建生产级产品时,您可能会遇到一些缺点。以下是其中一些:
Rust 编程的学习曲线非常陡峭
与其他流行语言(Go、Python、JavaScript 等)相比,掌握 Rust 语言并使用该语言构建生产级应用程序需要花费大量时间。
这不应该让你对使用 Rust 望而却步。掌握了 Rust,你就能真正高效地构建和部署应用程序,并获得使用 Rust 的所有好处。
Rust 程序编译时间长
编译时的内存和并发检查,再加上其他一些因素,导致 Rust 程序的编译时间很长。
根据应用程序的规模,较长的编译时间可能会在开发或生产阶段造成瓶颈。
Rust 的图书馆生态系统较小
与许多其他流行语言相比,Rust 是一种相对较新的语言,可以使用的库生态系统有限。
许多库(板条箱)仍在生产中,您可以访问 AreWeWebYet 等网站,了解可用于用 Rust 构建网络应用程序的生产就绪板条箱概览。
Rust 部署选项
Rust 已被广泛采用,因此您可以为您的应用程序选择多种部署方案。
大多数 Rust 部署选项都是基于 IaaS 或 CaaS 的平台。您可以根据自己的项目规格进行选择。
基础设施即服务(IaaS),如 AWS
基础设施即服务(IaaS)提供商为您提供基础设施,用于部署和管理在云上虚拟机上运行的应用程序。
您可以使用 IaaS 平台提供的服务,在运行 Linux、Windows、macOS 等操作系统和其他支持 Rust 的操作系统的虚拟机上部署 Rust 应用程序。
下面是一份流行的 IaaS 平台列表:
- Amazon Web Services
- Digital Ocean
- Google Cloud
- Linode
- Microsoft Azure
容器化即服务,如 Back4app Containers
容器化服务(CaaS)提供商可帮助您利用容器化技术促进应用程序的部署。
为了在支持容器化的平台上部署应用程序,您需要将应用程序及其所有依赖项捆绑到一个隔离的容器中。
容器是隔离的、可移植的,但你必须在 CaaS 提供商的功能范围内工作。
一些 IaaS 提供商提供 CaaS 功能。此外,还有一些平台只提供灵活的单独 CaaS 功能。
以下是一些 CaaS 平台的列表:
- Oracle Container Service
- Back4app
- Mirantix
- Docker Enterprise
Rust 应用程序部署流程
在本节中,您将了解如何将 Rust 应用程序部署到 Back4app 的 CaaS 平台。
什么是 Back4app?
Back4app 是一个云平台,您可以利用它为您的移动、网络和其他应用类型创建和部署各种类型的后端服务。
Back4app 提供了一个人工智能代理,您可以用它来简化应用程序在平台上的部署。您可以用它来管理 GitHub 代码库,在云上轻松部署代码,并管理正在运行的应用程序。
在 Back4app 的后端服务器上,可通过CaaS 功能部署和运行自定义容器。
使用容器镜像,您可以扩展应用程序的逻辑,而不必担心服务器架构的维护。
构建和部署
要学习本教程,您的电脑上必须已安装 Rust。您可以访问Rust 安装页面,了解不同的安装选项。
安装 Rust 后,创建一个终端会话,执行以下命令初始化一个新的 Rust 项目
mkdir back4app-rust-deployment && cd back4app-rust-deployment && cargo init
运行该命令后,你应该会在刚刚创建的新目录中看到一个cargo.toml
文件。你将使用cargo.toml
来管理依赖关系。
接下来,将这些指令添加到Cargo.toml
文件的[dependencies]
部分,以便在构建应用程序时安装这些依赖项。
[dependencies]
actix-web = "4.0"
serde = { version = "1.0", features = ["derive"] }
serde_derive = { version = "1.0" }
serde_json = "1.0"
lazy_static = "1.4"
actix-web
板块提供路由和其他 HTTP 相关功能,serde
、serde_derive
和serde_json
板块提供不同 JSON 操作的功能,lazy_static
板块提供运行时 API 的内存数据存储。
将这些导入添加到[main.rs]()
文件的顶部:
use serde::{Serialize, Deserialize};
use actix_web::{web, App, HttpServer, HttpResponse, Error};
use std::sync::Mutex;
extern crate lazy_static;
use lazy_static::lazy_static;
您可以根据需要的字段使用结构体来定义 API 的数据结构。下面的结构描述了一个人的 ID、用户名和电子邮件。
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Person {
pub id: i32,
pub username: String,
pub email: String,
}
[
derive
(序列化、反序列化、调试、克隆)]
是Serde_derive
crate 对Person
结构的实现,用于访问和使用其函数。
以下是如何使用lazy_static
crate 为您的 API 设置基于Person
结构类型的内存数据存储:
lazy_static! {
static ref DATA_STORE: Mutex<Vec<Person>> = Mutex::new(Vec::new());
}
您为 People 结构创建了一个懒惰初始化、线程安全的共享存储空间。您将在处理函数中使用它来存储和检索数据。
POST 处理程序功能
POST 请求处理函数接受Person
结构的 JSON 表示作为输入。然后,它会根据请求向客户端返回 HTTP 响应和错误信息。
在[main.rs]()
文件中添加此代码块,以实现 POST 请求处理程序功能。
async fn create_person(new_person: web::Json<Person>) -> Result<HttpResponse, Error> {
let mut data_store = DATA_STORE.lock().unwrap();
let new_id = data_store.len() as i32 + 1;
let mut person = new_person.into_inner();
person.id = new_id;
data_store.push(person.clone());
Ok(HttpResponse::Ok().json(person))
}
create_person
是一个异步函数,用于访问共享数据存储,为Person
结构生成一个新的 ID,将 JSON 表示的Person
转换为结构体,并将其推送到数据存储中。
请求成功后,该功能会向客户端提供输入数据库的数据以及 200 状态代码。
GET 处理程序函数
这里的 GET 处理器函数演示了读取数据存储中的所有数据并以 JSON 格式返回给客户端的过程。
在项目中添加以下代码块,以实现 GET 处理器功能
async fn get_people() -> Result<HttpResponse, Error> {
let data_store = DATA_STORE.lock().unwrap();
let people: Vec<Person> = data_store.clone();
Ok(HttpResponse::Ok().json(people))
}
get_people
函数是一个异步函数,它访问数据存储并将内容作为响应写入客户端。
请求成功后,函数会以200
状态代码向客户端回复数据存储中的所有数据。
PUT 处理程序函数
您的 PUT 请求处理函数应根据对象的字段更新数据存储中的条目。
下面介绍如何为您的 API 实现 PUT 处理程序函数:
async fn update_person(
id: web::Path<i32>,
person_update: web::Json<Person>,
) -> Result<HttpResponse, Error> {
let mut data_store = DATA_STORE.lock().unwrap();
if let Some(person) = data_store.iter_mut().find(|p| p.id == *id) {
*person = person_update.into_inner();
Ok(HttpResponse::Ok().json("Person updated successfully"))
} else {
Ok(HttpResponse::NotFound().json("Person not found"))
}
}
update_person
函数从请求中获取 ID 和新条目。然后遍历数据存储,如果存在新条目,则将其替换为新条目。
DELETE 处理程序函数
DELETE 请求函数只有一个参数,即请求中的 ID 字段。函数运行后,将从数据存储中删除带有 ID 的条目。
将此 DELETE 处理程序函数的实现添加到您的程序中。
// DELETE
pub async fn delete_person(id: web::Path<i32>) -> Result<HttpResponse, Error> {
let mut data_store = DATA_STORE.lock().unwrap();
if let Some(index) = data_store.iter().position(|p| p.id == *id) {
data_store.remove(index);
Ok(HttpResponse::Ok().json("Deleted successfully"))
} else {
Ok(HttpResponse::NotFound().json("Person not found"))
}
}
函数delete_person
会从数据存储中删除具有指定 ID 的条目。根据操作状态,函数会向客户端返回一个字符串和一个状态代码。
将处理程序函数映射到路由
定义端点后,您需要将路由映射到处理程序函数,以便访问处理程序函数的功能。
以下是为处理程序函数分配路由的方法:
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/person", web::post().to(create_person))
.route("/people", web::get().to(get_people))
.route("/person/{id}", web::put().to(update_person))
.route("/person/{id}", web::delete().to(delete_person))
})
.bind("0.0.0.0:8000")?
.run()
.await
}
主
函数是一个异步函数,用于将路由映射到处理函数后设置服务器。
HttpServer::new
函数实例化一个 HTTP 服务器,App::
new
()
函数创建一个新的应用程序实例,而route
函数则将路由映射到处理函数。
绑定
函数指定新应用程序的地址,运行
函数运行应用程序。
使用 Docker 将 Rust 应用程序容器化
Docker 是市场上最流行的容器化技术。您可以使用 Docker 将您的 Rust 应用程序容器化,以实现可移植性,并只需点击几下即可将其部署到 Back4app 上。
执行此命令可在项目中创建一个新的 Dockerfile:
touch Dockerfile
打开 Dockerfile,将这些构建说明添加到 Dockerfile 中:
# Use Rust Nightly as the base image
FROM rustlang/rust:nightly
# Set the working directory inside the container
WORKDIR /usr/src/myapp
# Copy the current directory contents into the container
COPY . .
# Build the application
RUN cargo build --release
# Expose port 8000
EXPOSE 8000
# Define the command to run the application
CMD ["./target/release/back4app-rust-deployment"]
这些说明指定了使用 Docker 容器化 Rust 应用程序的基础镜像和构建说明。
下面是 Dockerfile 的内容明细:
FROM rustlang/rust:nightly
指令指定了 Dockerfile 的基础镜像。Docker 会从版本库中提取该镜像,并在其上构建你的程序。WORKDIR /usr/src/myapp
指令为容器内的应用程序设置工作目录。COPY . .
指令会将工作目录中的所有内容复制到容器的当前工作目录中。RUN cargo build --release
指令执行在容器中构建应用程序的命令。EXPOSE 8000
指令暴露了容器的8000
端口,以便接收请求。CMD["./target/release/back4app-rust-deployment"]
运行程序(构建操作的可执行文件)。
写完 Dockerfile 后,就可以在 Back4app 的容器服务上部署容器了。
在 Back4app 上部署容器
您需要在 Back4app 上创建一个账户来部署容器。
以下是创建 Back4app 账户的步骤。
- 访问Back4app 网站
- 点击页面右上角的注册按钮。
- 填写注册表并提交,即可创建账户。
成功创建 Back4app 账户后,请登录并点击登陆页面右上角的 “新建 APP
“按钮。
您将看到一些选项,以选择构建应用程序的方式。选择 “容器即服务 "
选项。
现在,将 Github 账户连接到 Back4app 账户,并配置对账户或特定项目中的软件源的访问权限。
选择要部署的应用程序(本教程中的应用程序),然后单击选择。
点击 “选择 “后,该按钮将带您进入一个页面,您可以在此填写应用程序的相关信息,包括分支名称、根目录和环境变量。
部署过程自动启动、
使用 Back4app AI 代理进行部署
如下图所示,您还可以使用Back4app AI 代理部署应用程序,以加快开发工作流程:
请点击 在GitHub 账户中安装 Back4app 容器应用程序,并按照上图中的步骤进行配置。
完成应用程序设置后,您就可以继续使用人工智能代理部署应用程序了。
按照提供的链接监控应用程序的部署进度。
结论
您已学会如何在 Back4app 上构建和部署 Docker 容器化的 Rust 应用程序。
将应用程序部署到 Back4app 是简化后端基础架构管理的好方法。
Back4App 提供强大的工具来管理数据、扩展应用程序并监控其性能。
对于希望构建优秀应用程序而不是管理服务器的开发人员来说,这是一个极佳的选择。