使用 Cargo Lambda 构建 Rust Lambda 函数 - Amazon Serverless Application Model
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 Cargo Lambda 构建 Rust Lambda 函数

此功能位于 Amazon SAM 的预览版中,可能会发生变化。

将 Amazon Serverless Application Model 命令行界面 (Amazon SAM CLI) 和 Rust Amazon Lambda 函数结合使用。

先决条件

Rust 语言

要安装 Rust,请参阅 Rust 语言网站上的安装 Rust

Cargo Lambda

Amazon SAM CLI 要求安装 Cargo Lambda,是 Cargo 的子命令。有关安装说明,请参阅 Cargo Lambda 文档中的安装

Docker

构建和测试 Rust Lambda 函数需要 Docker。有关安装说明,请参阅安装 Docker

选择加入 Amazon SAM CLI 测试版功能

由于此功能为预览版,因此您必须使用以下方法之一选择加入:

  1. 使用环境变量:SAM_CLI_BETA_RUST_CARGO_LAMBDA=1

  2. 在您的 samconfig.toml 文件中添加以下内容:

    [default.build.parameters] beta_features = true [default.sync.parameters] beta_features = true
  3. 使用支持的 Amazon SAM CLI 命令时使用 --beta-features 选项。例如:

    $ sam build --beta-features
  4. 当 Amazon SAM CLI 提示您选择加入时,请选择选项 y。以下是 示例:

    $ sam build Starting Build use cache Build method "rust-cargolambda" is a beta feature. Please confirm if you would like to proceed You can also enable this beta feature with "sam build --beta-features". [y/N]: y

配置 Amazon SAM 与 Rust Lambda 函数一起使用

第 1 步:配置 Amazon SAM 模板

通过以下操作配置您的 Amazon SAM 模板:

  • 二进制 – 可选。指定模板何时包含多个 Rust Lambda 函数。

  • BuildMethodrust-cargolambda.

  • CodeUriCargo.toml 文件路径。

  • 处理程序bootstrap.

  • 运行时系统provided.al2.

要了解有关自定义运行时的更多信息,请参阅《Amazon Lambda 开发人员指南》中的自定义 Amazon Lambda 运行时

以下是已配置 Amazon SAM 模板的示例:

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 ... Resources: MyFunction: Type: AWS::Serverless::Function Metadata: BuildMethod: rust-cargolambda BuildProperties: function_a Properties: CodeUri: ./rust_app Handler: bootstrap Runtime: provided.al2 ...

第 2 步:将 Amazon SAM CLI 与 Rust Lambda 函数一起使用

在 Amazon SAM 模板中使用任意 Amazon SAM CLI 命令。有关更多信息,请参阅 使用 Amazon SAM CLI

示例

Hello World 示例

在此示例中,我们使用 Rust 作为运行时系统来构建示例 Hello World 应用程序。

首先,我们使用 sam init 初始化新的无服务器应用程序。在交互式流程中,我们选择 Hello World 应用程序并选择 Rust 运行时系统。

$ sam init ... Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Choose an AWS Quick Start application template 1 - Hello World Example 2 - Multi-step workflow 3 - Serverless API ... Template: 1 Use the most popular runtime and package type? (Python and zip) [y/N]: ENTER Which runtime would you like to use? 1 - aot.dotnet7 (provided.al2) 2 - dotnet6 3 - dotnet5.0 ... 18 - python3.7 19 - python3.10 20 - ruby2.7 21 - rust (provided.al2) Runtime: 21 Based on your selections, the only Package type available is Zip. We will proceed to selecting the Package type as Zip. Based on your selections, the only dependency manager available is cargo. We will proceed copying the template using cargo. Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: ENTER Would you like to enable monitoring using CloudWatch Application Insights? For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: ENTER Project name [sam-app]: hello-rust ----------------------- Generating application: ----------------------- Name: hello-rust Runtime: rust (provided.al2) Architectures: x86_64 Dependency Manager: cargo Application Template: hello-world Output Directory: . Configuration file: hello-rust/samconfig.toml Next steps can be found in the README file at hello-rust/README.md Commands you can use next ========================= [*] Create pipeline: cd hello-rust && sam pipeline init --bootstrap [*] Validate SAM template: cd hello-rust && sam validate [*] Test Function in the Cloud: cd hello-rust && sam sync --stack-name {stack-name} --watch

以下是 Hello World 应用程序的结构:

hello-rust
├── README.md
├── events
│   └── event.json
├── rust_app
│   ├── Cargo.toml
│   └── src
│       └── main.rs
├── samconfig.toml
└── template.yaml

在 Amazon SAM 模板中,Rust 函数定义如下:

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 ... Resources: HelloWorldFunction: Type: AWS::Serverless::Function Metadata: BuildMethod: rust-cargolambda Properties: CodeUri: ./rust_app Handler: bootstrap Runtime: provided.al2 Architectures: - x86_64 Events: HelloWorld: Type: Api Path: /hello Method: get

接下来,运行 sam build 以构建应用程序并准备部署。Amazon SAM CLI 创建一个 .aws-sam 目录并在其中整理构建构件。函数是使用 Cargo Lambda 构建,并以可执行二进制文件的形式存储于 .aws-sam/build/HelloWorldFunction/bootstrap

hello-rust$ sam build Starting Build use cache Build method "rust-cargolambda" is a beta feature. Please confirm if you would like to proceed You can also enable this beta feature with "sam build --beta-features". [y/N]: y Experimental features are enabled for this session. Visit the docs page to learn more about the AWS Beta terms https://aws.amazon.com/service-terms/. Cache is invalid, running build and copying resources for following functions (HelloWorldFunction) Building codeuri: /Users/.../hello-rust/rust_app runtime: provided.al2 metadata: {'BuildMethod': 'rust-cargolambda'} architecture: x86_64 functions: HelloWorldFunction Running RustCargoLambdaBuilder:CargoLambdaBuild Running RustCargoLambdaBuilder:RustCopyAndRename Build Succeeded Built Artifacts : .aws-sam/build Built Template : .aws-sam/build/template.yaml Commands you can use next ========================= [*] Validate SAM template: sam validate [*] Invoke Function: sam local invoke [*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch [*] Deploy: sam deploy --guided

接下来,使用 sam deploy --guided 部署应用程序。

hello-rust$ sam deploy --guided Configuring SAM deploy ====================== Looking for config file [samconfig.toml] : Found Reading default arguments : Success Setting default arguments for 'sam deploy' ========================================= Stack Name [hello-rust]: ENTER AWS Region [us-west-2]: ENTER #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [Y/n]: ENTER #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: ENTER #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: ENTER HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y Save arguments to configuration file [Y/n]: ENTER SAM configuration file [samconfig.toml]: ENTER SAM configuration environment [default]: ENTER Looking for resources needed for deployment: ... Uploading to hello-rust/56ba6585d80577dd82a7eaaee5945c0b 817973 / 817973 (100.00%) Deploying with following values =============================== Stack name : hello-rust Region : us-west-2 Confirm changeset : True Disable rollback : False Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1a4x26zbcdkqr Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {} Signing Profiles : {} Initiating deployment ===================== Uploading to hello-rust/a4fc54cb6ab75dd0129e4cdb564b5e89.template 1239 / 1239 (100.00%) Waiting for changeset to be created.. CloudFormation stack changeset --------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType Replacement --------------------------------------------------------------------------------------------------------- + Add HelloWorldFunctionHelloW AWS::Lambda::Permission N/A orldPermissionProd ... --------------------------------------------------------------------------------------------------------- Changeset created successfully. arn:aws:cloudformation:us-west-2:012345678910:changeSet/samcli-deploy1681427201/f0ef1563-5ab6-4b07-9361-864ca3de6ad6 Previewing CloudFormation changeset before deployment ====================================================== Deploy this changeset? [y/N]: y 2023-04-13 13:07:17 - Waiting for stack create/update to complete CloudFormation events from stack operations (refresh every 5.0 seconds) --------------------------------------------------------------------------------------------------------- ResourceStatus ResourceType LogicalResourceId ResourceStatusReason --------------------------------------------------------------------------------------------------------- CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole - CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation ... --------------------------------------------------------------------------------------------------------- CloudFormation outputs from deployed stack --------------------------------------------------------------------------------------------------------- Outputs --------------------------------------------------------------------------------------------------------- Key HelloWorldFunctionIamRole Description Implicit IAM Role created for Hello World function Value arn:aws:iam::012345678910:role/hello-rust-HelloWorldFunctionRole-10II2P13AUDUY Key HelloWorldApi Description API Gateway endpoint URL for Prod stage for Hello World function Value https://ggdxec9le9.execute-api.us-west-2.amazonaws.com/Prod/hello/ Key HelloWorldFunction Description Hello World Lambda Function ARN Value arn:aws:lambda:us-west-2:012345678910:function:hello-rust-HelloWorldFunction- yk4HzGzYeZBj --------------------------------------------------------------------------------------------------------- Successfully created/updated stack - hello-rust in us-west-2

为了进行测试,我们可以使用 API 端点调用 Lambda 函数。

$ curl https://ggdxec9le9.execute-api.us-west-2.amazonaws.com/Prod/hello/ Hello World!%

要在本地测试函数,首先我们要确保函数的 Architectures 属性与本地计算机相匹配。

... Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Metadata: BuildMethod: rust-cargolambda # More info about Cargo Lambda: https://github.com/cargo-lambda/cargo-lambda Properties: CodeUri: ./rust_app # Points to dir of Cargo.toml Handler: bootstrap # Do not change, as this is the default executable name produced by Cargo Lambda Runtime: provided.al2 Architectures: - arm64 ...

由于我们在此示例中将基础设施从 x86_64 修改为 arm64,因此我们运行 sam build 以更新构建构件。然后运行 sam local invoke 在本地调用函数。

hello-rust$ sam local invoke Invoking bootstrap (provided.al2) Local image was not found. Removing rapid images for repo public.ecr.aws/sam/emulation-provided.al2 Building image..................................................................................................................................... Using local image: public.ecr.aws/lambda/provided:al2-rapid-arm64. Mounting /Users/.../hello-rust/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated, inside runtime container START RequestId: fbc55e6e-0068-45f9-9f01-8e2276597fc6 Version: $LATEST {"statusCode":200,"body":"Hello World!"}END RequestId: fbc55e6e-0068-45f9-9f01-8e2276597fc6 REPORT RequestId: fbc55e6e-0068-45f9-9f01-8e2276597fc6 Init Duration: 0.68 ms Duration: 130.63 ms Billed Duration: 131 ms Memory Size: 128 MB Max Memory Used: 128 MB

单个 Lambda 函数项目

以下是一个包含单个 Rust Lambda 函数的无服务器应用程序的示例。

项目目录结构:

.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── template.yaml

Amazon SAM 模板:

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 ... Resources: MyFunction: Type: AWS::Serverless::Function Metadata: BuildMethod: rust-cargolambda Properties: CodeUri: ./ Handler: bootstrap Runtime: provided.al2 ...

多个 Lambda 函数项目

以下是一个包含多个 Rust Lambda 函数的无服务器应用程序的示例。

项目目录结构:

.
├── Cargo.lock
├── Cargo.toml
├── src
│   ├── function_a.rs
│   └── function_b.rs
└── template.yaml

Amazon SAM 模板:

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 ... Resources: FunctionA: Type: AWS::Serverless::Function Metadata: BuildMethod: rust-cargolambda BuildProperties: Binary: function_a Properties: CodeUri: ./ Handler: bootstrap Runtime: provided.al2 FunctionB: Type: AWS::Serverless::Function Metadata: BuildMethod: rust-cargolambda BuildProperties: Binary: function_b Properties: CodeUri: ./ Handler: bootstrap Runtime: provided.al2

Cargo.toml 文件:

[package] name = "test-handler" version = "0.1.0" edition = "2021" [dependencies] lambda_runtime = "0.6.0" serde = "1.0.136" tokio = { version = "1", features = ["macros"] } tracing = { version = "0.1", features = ["log"] } tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] } [[bin]] name = "function_a" path = "src/function_a.rs" [[bin]] name = "function_b" path = "src/function_b.rs"