定义采用 Rust 的 Lambda 函数处理程序
注意
Rust 运行时系统客户端
Lambda 函数处理程序是函数代码中处理事件的方法。当调用函数时,Lambda 运行处理程序方法。您的函数会一直运行,直到处理程序返回响应、退出或超时。
Rust 处理程序基础知识
将 Lambda 函数代码编写为 Rust 可执行文件。实施处理程序函数代码和主函数,并包括以下内容:
-
来自 crates.io 的 lambda_runtime
crate,可实现适用于 Rust 的 Lambda 编程模型。 -
将 Tokio
包含在依赖项中。适用于 Lambda 的 Rust 运行时系统客户端 使用 Tokio 来处理异步调用。
例 – 处理 JSON 事件的 Rust 处理程序
以下示例使用 serde_json
use lambda_runtime::{service_fn, LambdaEvent, Error}; use serde_json::{json, Value}; async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> { let payload = event.payload; let first_name = payload["firstName"].as_str().unwrap_or("world"); Ok(json!({ "message": format!("Hello, {first_name}!") })) } #[tokio::main] async fn main() -> Result<(), Error> { lambda_runtime::run(service_fn(handler)).await }
请注意以下几点:
-
use
:导入 Lambda 函数所需的库。 -
async fn main
:运行 Lambda 函数代码的入口点。Rust 运行时系统客户端使用 Tokio作为异步运行时系统,因此您必须使用 #[tokio::main]
为主函数添加注释。 -
async fn handler(event: LambdaEvent<Value>) -> Result<Value,
Error
>
:这是 Lambda 处理程序签名。包括调用函数时运行的代码。-
LambdaEvent<Value>
:这是一种泛型类型,用于描述 Lambda 运行时系统以及 Lambda 函数上下文接收到的事件。 -
Result<Value, Error>
:函数返回Result
类型。如果函数成功,则结果为 JSON 值。如果函数不成功,则结果为错误。
-
使用共享状态
您可以声明独立于 Lambda 函数的处理程序代码的共享变量。这些变量可以帮助您在函数接收任何事件之前的 Init 阶段 期间加载状态信息。
例 – 跨函数实例共享 Amazon S3 客户端
请注意以下几点:
-
use aws_sdk_s3::Client
:此示例要求您将aws-sdk-s3 = "0.26.0"
添加到Cargo.toml
文件中的依赖项列表。 -
aws_config::from_env
:此示例要求您将aws-config = "0.55.1"
添加到Cargo.toml
文件中的依赖项列表。
use aws_sdk_s3::Client; use lambda_runtime::{service_fn, Error, LambdaEvent}; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] struct Request { bucket: String, } #[derive(Serialize)] struct Response { keys: Vec<String>, } async fn handler(client: &Client, event: LambdaEvent<Request>) -> Result<Response, Error> { let bucket = event.payload.bucket; let objects = client.list_objects_v2().bucket(bucket).send().await?; let keys = objects .contents() .map(|s| s.iter().flat_map(|o| o.key().map(String::from)).collect()) .unwrap_or_default(); Ok(Response { keys }) } #[tokio::main] async fn main() -> Result<(), Error> { let shared_config = aws_config::from_env().load().await; let client = Client::new(&shared_config); let shared_client = &client; lambda_runtime::run(service_fn(move |event: LambdaEvent<Request>| async move { handler(&shared_client, event).await })) .await }
Rust Lambda 函数的代码最佳实践
在构建 Lambda 函数时,请遵循以下列表中的指南,采用最佳编码实践:
-
从核心逻辑中分离 Lambda 处理程序。这样您可以创建更容易进行单元测试的函数。
-
将依赖关系的复杂性降至最低。首选在执行环境启动时可以快速加载的更简单的框架。
-
将部署程序包大小精简为只包含运行时必要的部分。这样会减少调用前下载和解压缩部署程序包所需的时间。
-
利用执行环境重用来提高函数性能。连接软件开发工具包 (SDK) 客户端和函数处理程序之外的数据库,并在
/tmp
目录中本地缓存静态资产。由函数的同一实例处理的后续调用可重用这些资源。这样就可以通过缩短函数运行时间来节省成本。为了避免调用之间潜在的数据泄露,请不要使用执行环境来存储用户数据、事件或其他具有安全影响的信息。如果您的函数依赖于无法存储在处理程序的内存中的可变状态,请考虑为每个用户创建单独的函数或单独的函数版本。
-
使用 keep-alive 指令来维护持久连接。Lambda 会随着时间的推移清除空闲连接。在调用函数时尝试重用空闲连接会导致连接错误。要维护您的持久连接,请使用与运行时关联的 keep-alive 指令。有关示例,请参阅在 Node.js 中通过 Keep-Alive 重用连接。
-
使用环境变量将操作参数传递给函数。例如,您在写入 Amazon S3 存储桶时,不应对要写入的存储桶名称进行硬编码,而应将存储桶名称配置为环境变量。
-
避免在 Lambda 函数中使用递归调用,在这种情况下,函数会调用自己或启动可能再次调用该函数的进程。这可能会导致意想不到的函数调用量和升级成本。如果您看到意外的调用量,请立即将函数保留并发设置为
0
来限制对函数的所有调用,同时更新代码。 -
Lambda 函数代码中不要使用非正式的非公有 API。对于 AWS Lambda 托管式运行时,Lambda 会定期为 Lambda 的内部 API 应用安全性和功能更新。这些内部 API 更新可能不能向后兼容,会导致意外后果,例如,假设您的函数依赖于这些非公有 API,则调用会失败。请参阅 API 参考以查看公开发布的 API 列表。
-
编写幂等代码。为您的函数编写幂等代码可确保以相同的方式处理重复事件。您的代码应该正确验证事件并优雅地处理重复事件。有关更多信息,请参阅如何使我的 Lambda 函数具有幂等性?
。