定义采用 Rust 的 Lambda 函数处理程序 - AWS Lambda

定义采用 Rust 的 Lambda 函数处理程序

注意

Rust 运行时系统客户端是实验性程序包。它随时可能更改,并且仅用于评估目的。

Lambda 函数处理程序是函数代码中处理事件的方法。当调用函数时,Lambda 运行处理程序方法。您的函数会一直运行,直到处理程序返回响应、退出或超时。

Rust 处理程序基础知识

将 Lambda 函数代码编写为 Rust 可执行文件。实施处理程序函数代码和主函数,并包括以下内容:

例 – 处理 JSON 事件的 Rust 处理程序

以下示例使用 serde_json crate 来处理基本 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 函数具有幂等性?