View a markdown version of this page

在 Cargo Lambda中使用 建置 Rust Lambda 函數 AWS SAM - AWS Serverless Application Model

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

在 Cargo Lambda中使用 建置 Rust Lambda 函數 AWS SAM

使用 AWS Serverless Application Model 命令列界面 (AWS SAM CLI) 搭配 Rust AWS Lambda 函數。

先決條件

Rust 語言

若要安裝 Rust,請參閱在Rust語言網站安裝 Rust

Cargo Lambda

AWS SAM CLI 需要安裝 Cargo Lambda,這是 的子命令Cargo。如需安裝說明,請參閱 Cargo Lambda 文件中的安裝

Docker

建置和測試 Rust Lambda 函數需要 Docker。如需安裝指示,請參閱安裝 Docker

設定 AWS SAM 搭配 Rust Lambda 函數使用

步驟 1:設定您的 AWS SAM 範本

使用下列項目設定您的 AWS SAM 範本:

  • 二進位 – 選用。指定單一Cargo套件何時定義多個二進位檔,以識別要為此函數建置的二進位檔。當每個函數都是自己的Cargo套件時,例如在Cargo工作區中,您不需要此屬性。

  • BuildMethodrust-cargolambda

  • CodeUriCargo.toml 檔案的路徑。

  • 處理常式 – bootstrap

  • 執行時間provided.al2023

若要進一步了解自訂執行期,請參閱《 AWS Lambda 開發人員指南》中的自訂 AWS Lambda 執行期

以下是已設定 AWS 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.al2023 ...

步驟 2:搭配 Rust Lambda 函數使用 AWS SAM CLI

將任何 AWS SAM CLI命令與 AWS SAM 範本搭配使用。如需詳細資訊,請參閱AWS 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 - dotnet8 2 - dotnet6 3 - go (provided.al2) ... 18 - python3.11 19 - python3.10 20 - ruby4.0 21 - ruby3.3 22 - ruby3.2 23 - rust (provided.al2) 24 - rust (provided.al2023) Runtime: 24 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.al2023) 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

在我們的 AWS 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.al2023 Architectures: - x86_64 Events: HelloWorld: Type: Api Properties: Path: /hello Method: get

接下來,我們會執行 sam build來建置應用程式並準備部署。 AWS SAM CLI 會建立.aws-sam目錄,並在其中組織我們的建置成品。我們的函數是使用 建置,Cargo Lambda並存放在 的可執行二進位檔.aws-sam/build/HelloWorldFunction/bootstrap

注意

如果您打算在 MacOS 中執行 sam local invoke命令,您需要先建置不同的函數,才能叫用 。若要執行此作業,請使用下列命令:

  • SAM_BUILD_MODE=debug sam build

只有在完成本機測試時,才需要此命令。建置 以進行部署時,不建議這麼做。

hello-rust$ sam build Starting Build use cache Cache is invalid, running build and copying resources for following functions (HelloWorldFunction) Building codeuri: /Users/.../hello-rust/rust_app runtime: provided.al2023 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-samclisam-s3-demo-bucket-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.al2023 Architectures: - arm64 ...

由於我們在此範例中arm64將架構從 修改x86_64為 ,因此我們執行 sam build來更新建置成品。然後,我們會執行 sam local invoke以本機叫用函數。

hello-rust$ sam local invoke Invoking bootstrap (provided.al2023) Local image was not found. Removing rapid images for repo public.ecr.aws/sam/emulation-provided.al2023 Building image..................................................................................................................................... Using local image: public.ecr.aws/lambda/provided:al2023-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

AWS 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.al2023 ...

多個 Lambda 函數專案

以下是無伺服器應用程式的範例,其中包含多個 Rust Lambda 函數,組織為Cargo工作區。

對於具有多個 Rust Lambda 函數的應用程式,我們建議使用Cargo工作區。每個函數都是自己的套件,因此函數可以在透過程式庫套件共用常見程式碼時宣告獨立相依性。每個套件都會產生以套件命名的單一二進位檔,因此您不需要設定Binary建置屬性。

專案目錄結構:

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

工作區Cargo.toml檔案,位於專案根目錄:

[workspace] resolver = "2" members = [ "function_a", "function_b", ] [workspace.dependencies] lambda_runtime = "0.13" serde = { version = "1", features = ["derive"] } tokio = { version = "1", features = ["macros", "rt"] }

Cargo.toml 每個函數的 檔案,例如 function_a/Cargo.toml

[package] name = "function_a" version = "0.1.0" edition = "2021" [dependencies] lambda_runtime = { workspace = true } serde = { workspace = true } tokio = { workspace = true }

AWS SAM 範本。每個函數CodeUri的 指向該函數的套件目錄:

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

會將工作區中的每個函數 AWS SAM CLI建置到工作區的共用target目錄中,因此 會為每個函數Cargo編譯一次共用相依性,而不是一次。此行為需要 AWS SAM CLI 1.165.0 版或更新版本。在舊版上,每個函數都內建在自己的target目錄中,並且會針對每個函數重新編譯完整的相依性樹狀結構,這使得在新增函數時建置速度變慢。

為每個函數套件提供一個唯一的二進位名稱。套件名稱在工作區中是唯一的,因此預設的二進位名稱已經是唯一的。如果您使用[[bin]]區段覆寫二進位名稱,請勿為兩個套件提供相同的二進位名稱。它們會編譯至共用target目錄中的相同路徑,並互相覆寫。當 偵測到此問題時, 會 AWS SAM CLI記錄警告。

或者,單一套件可以定義多個二進位檔。在這種情況下,請使用Binary建置屬性來選取每個函數的二進位檔:

Resources: FunctionA: Type: AWS::Serverless::Function Metadata: BuildMethod: rust-cargolambda BuildProperties: Binary: function_a Properties: CodeUri: ./ Handler: bootstrap Runtime: provided.al2023

在 中最佳化 Rust 建置 GitHub Actions

Rust 建置是運算密集型,而持續整合執行器會從沒有編譯成品開始。具有數個共用大型相依性之函數的應用程式,例如 AWS SDK,可以花費其大部分建置時間來編譯相同的相依性。下列實務可減少 中的建置時間GitHub Actions。

針對工作區使用 AWS SAM CLI 1.165.0 版或更新版本

1.165.0 版和更新版本會將Cargo工作區的每個成員建置到工作區的共用target目錄中,因此共用相依性會針對每個組建編譯一次,而不是針對每個函數編譯一次。在安裝 AWS SAM CLI 時指定最低版本,讓組建不會無提示地回復到較慢的行為。

快取Cargo登錄檔和target目錄

在執行之間快取Cargo登錄檔 (~/.cargo/registry~/.cargo/git/db) 和工作區target目錄,以便還原不變的相依性,而不是重新編譯。為每個編譯目標使用單獨的快取。跨編譯 發行成品的任務arm64會產生與原生編譯 的任務不同的成品x86_64,因此共用快取永遠不會相符。

在快取金鑰中包含建置設定

Cargo 包含 opt-level和 等設定codegen-units,用於決定是否可以重複使用編譯的成品。如果您變更工作區Cargo.toml檔案的 [profile.release]區段而不變更快取金鑰,快取會還原,但無論如何都會重新編譯每個木箱。在快取金鑰中包含工作區Cargo.toml檔案的雜湊,以便變更設定檔設定會啟動新的快取。

遞交您的Cargo.lock檔案

Lambda 函數是可執行檔,因此請遞交您的Cargo.lock檔案。這為您提供可重現的建置和穩定的快取金鑰,只有在相依性變更時才會變更。

針對建置時間和冷啟動調校發行設定檔

您的函數程式碼會在每次執行時重新編譯,因為它變更的頻率高於您的相依性。預設版本描述檔會最佳化執行時間輸送量,許多 Lambda 函數不需要。大小最佳化會產生較小的二進位檔,這也有助於冷啟動時間,並且增加程式碼產生單位的數量會在編譯期間增加平行處理。停用連結時間最佳化 (lto),因為它會使編譯速度變慢。將下列項目新增至工作區Cargo.toml檔案:

[profile.release] opt-level = "s" codegen-units = 256 lto = false strip = true

測量對您自己應用程式的影響。這些設定會針對建置時間和二進位大小,交換少量的執行時間效能。

避免重複的工作流程執行

pushpull_request事件上執行的工作流程會針對相同的遞交執行兩次。 GitHub Actions快取的範圍依分支和提取請求而定,因此兩者會執行寫入不同的快取範圍,而且不會重複使用另一個快取。使用在前端遞交上鍵控的並行群組,以便只有一個執行會建置每個遞交。

下列工作流程會為 建置 Rust Lambda 函數的Cargo工作區arm64,並套用上述實務:

name: Build on: push: branches: [main] pull_request: # Collapse the push and pull_request runs for the same commit into a single run. concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.head.sha || github.sha }} cancel-in-progress: true jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable with: targets: aarch64-unknown-linux-gnu # Cache the Cargo registry and the workspace target directory. The key covers # the compilation target, Cargo.lock, and the workspace Cargo.toml, so that # changing a dependency or a release profile setting starts a new cache # instead of restoring one whose artifacts Cargo discards. - uses: actions/cache@v4 with: path: | ~/.cargo/registry/index ~/.cargo/registry/cache ~/.cargo/git/db target key: cargo-arm64-${{ hashFiles('Cargo.lock', 'Cargo.toml') }} restore-keys: | cargo-arm64- - name: Install build tools run: pip install cargo-lambda 'aws-sam-cli>=1.165.0' - name: Build run: sam build

當金鑰不完全相符時,restore-keys項目可讓執行從最新的快取開始,因此相依性變更會重複使用未變更的木箱,而不是再次編譯所有項目。