2个版本
| 0.1.1 | 2019年5月3日 |
|---|---|
| 0.1.0 | 2019年1月25日 |
#703 在 网络编程
1,613 每月下载量
在 23 个crate(3个直接) 中使用
20KB
442 行
Rust AWS Lambda运行时
此包使您能够轻松运行用Rust编写的AWS Lambda函数。此工作空间包括多个crate
lambda-runtime是一个库,为用Rust编写的应用程序提供Lambda运行时。lambda-http是一个库,使您能够在Rust中轻松编写API Gateway代理事件集中的Lambda函数。lambda-extension是一个库,使您能够在Rust中轻松编写Lambda运行时扩展。lambda-events是一个库,提供Rust中强类型化的Lambda事件结构。lambda-runtime-api-client是lambda运行时和lambda扩展库之间的共享库,它包含一个用于与AWS Lambda运行时API通信的通用API客户端。
Rust运行时客户端是一个实验性包。它可能会更改,仅用于评估目的。
入门指南
使用Rust编写Lambda函数最简单的方式是通过使用Cargo Lambda,这是一个相关项目。Cargo Lambda是一个Cargo插件或子命令,它提供了一些命令来帮助你在AWS Lambda上使用Rust。
推荐使用包管理器安装Cargo Lambda。
1- 在MacOS上使用Homebrew
brew tap cargo-lambda/cargo-lambda
brew install cargo-lambda
2- 在Windows上使用Scoop
scoop bucket add cargo-lambda https://github.com/cargo-lambda/scoop-cargo-lambda
scoop install cargo-lambda/cargo-lambda
或者在安装了Python 3的任何系统上使用PiP
pip3 install cargo-lambda
在Cargo Lambda文档中查看其他安装选项。
您的第一个函数
要创建您的第一个函数,运行带有子命令new的Cargo Lambda。此命令将为您的函数生成一个带有初始源代码的Rust包
cargo lambda new YOUR_FUNCTION_NAME
示例函数
如果您想手动创建第一个函数,下面的代码演示了一个简单的函数,该函数接收一个包含firstName字段的event,并返回一个消息给调用者。
use lambda_runtime::{service_fn, LambdaEvent, Error};
use serde_json::{json, Value};
#[tokio::main]
async fn main() -> Result<(), Error> {
let func = service_fn(func);
lambda_runtime::run(func).await?;
Ok(())
}
async fn func(event: LambdaEvent<Value>) -> Result<Value, Error> {
let (event, _context) = event.into_parts();
let first_name = event["firstName"].as_str().unwrap_or("world");
Ok(json!({ "message": format!("Hello, {}!", first_name) }))
}
构建和部署您的Lambda函数
如果您已经在您的机器上安装了Cargo Lambda,请运行以下命令来构建您的函数
cargo lambda build --release
还有其他构建函数的方法:使用AWS CLI手动构建,使用AWS SAM,以及使用Serverless框架。
1. 交叉编译Lambda函数
默认情况下,Cargo Lambda将您的函数构建为在x86_64架构上运行。如果您想使用不同的架构,请使用以下选项。
1.2. 构建 Lambda 函数
Amazon Linux 2
我们建议您尽可能使用Amazon Linux 2运行时(例如provided.al2)来在Rust中构建Lambda函数。要为Amazon Linux 2运行时构建Lambda函数,请运行
cargo lambda build --release --arm64
Amazon Linux 1
Amazon Linux 1使用glibc版本2.17,而Rust的二进制文件默认需要2.18或更高版本的glibc。但是,使用Cargo Lambda,您可以指定不同的glibc版本。
如果您正在为Amazon Linux 1构建,或者您想同时支持Amazon Linux 2和1,请运行
cargo lambda build --release --target aarch64-unknown-linux-gnu.2.17
注意 如果您正在为x86_64构建,请将“aarch64”替换为“x86_64”
2. 将二进制文件部署到AWS Lambda
对于自定义运行时,AWS Lambda会在部署包zip中查找名为bootstrap的可执行文件。将生成的可执行文件重命名为bootstrap并将其添加到zip存档中。
您可以在target/lambda目录下找到您函数的bootstrap二进制文件。
2.2. 使用Cargo Lambda部署
一旦您使用前面描述的选项之一构建了代码,请使用deploy子命令将您的函数上传到AWS
cargo lambda deploy \
--iam-role arn:aws:iam::XXXXXXXXXXXXX:role/your_lambda_execution_role
警告 确保将执行角色替换为您账户中现有的角色!
此命令将创建一个与您的Rust包同名Lambda函数。您可以通过在命令末尾添加参数来更改函数的名称
cargo lambda deploy \
--iam-role arn:aws:iam::XXXXXXXXXXXXX:role/your_lambda_execution_role \
my-first-lambda-function
注意 请参阅Cargo Lambda文档中的其他部署选项。
您可以使用invoke子命令来测试函数
cargo lambda invoke --remote \
--data-ascii '{"command": "hi"}' \
--output-format json \
my-first-lambda-function
注意 示例中的 CLI 命令使用的是 Linux/MacOS 语法。对于 Windows CMD 或 PowerShell 等不同的外壳,当使用嵌套引号如
'{"command": "hi"}'时,需要修改语法。使用反斜杠进行转义可能有必要。有关更多信息,请参阅 AWS CLI 参考文档。
2.2. 使用 AWS CLI 部署
您还可以使用 AWS CLI 部署您的 Rust 函数。首先,您需要创建函数的 ZIP 归档。如果添加了 output-format 标志,Cargo Lambda 可以在构建二进制文件时自动为您完成。
cargo lambda build --release --arm64 --output-format zip
生成的 zip 文件可以在 target/lambda/YOUR_PACKAGE/bootstrap.zip 中找到。使用该文件路径使用 AWS CLI 部署您的函数。
$ aws lambda create-function --function-name rustTest \
--handler bootstrap \
--zip-file fileb://./target/lambda/basic/bootstrap.zip \
--runtime provided.al2023 \ # Change this to provided.al2 if you would like to use Amazon Linux 2 (or to provided.al for Amazon Linux 1).
--role arn:aws:iam::XXXXXXXXXXXXX:role/your_lambda_execution_role \
--environment Variables={RUST_BACKTRACE=1} \
--tracing-config Mode=Active
警告 确保将执行角色替换为您账户中现有的角色!
现在,您可以使用 AWS CLI 或 AWS Lambda 控制台测试该函数。
$ aws lambda invoke
--cli-binary-format raw-in-base64-out \
--function-name rustTest \
--payload '{"command": "Say Hi!"}' \
output.json
$ cat output.json # Prints: {"msg": "Command Say Hi! executed."}
注意 在使用 AWS CLI 版本 2 时,
--cli-binary-format raw-in-base64-out是必需的参数。有关更多信息,请参阅 更多信息
2.3. AWS 无服务器应用程序模型 (SAM)
您可以使用 AWS Serverless Application Model (SAM) 使用在 Rust 中构建的 Lambda 函数。为此,您需要安装 AWS SAM CLI,这将帮助您在 AWS 账户中打包和部署 Lambda 函数。
您需要创建一个包含您所需基础设施的 template.yaml 文件。以下是一个包含单个 Lambda 函数的示例。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 128
Architectures: ["arm64"]
Handler: bootstrap
Runtime: provided.al2023
Timeout: 5
CodeUri: target/lambda/basic/
Outputs:
FunctionName:
Value: !Ref HelloWorldFunction
Description: Name of the Lambda function
然后,您可以使用 AWS SAM CLI 部署您的 Lambda 函数。
sam deploy --guided
最后,sam 将输出实际的 Lambda 函数名称。您可以使用此名称调用您的函数。
$ aws lambda invoke
--cli-binary-format raw-in-base64-out \
--function-name HelloWorldFunction-XXXXXXXX \ # Replace with the actual function name
--payload '{"command": "Say Hi!"}' \
output.json
$ cat output.json # Prints: {"msg": "Command Say Hi! executed."}
2.4. Serverless 框架
或者,您可以使用 Serverless 框架 Rust 插件 声明性地构建基于 Rust 的 Lambda 函数。
存在许多入门级 Serverless 应用程序模板,可以帮助您快速启动。
- 一个最小的 echo 函数,以演示最小的 Rust 函数设置看起来像什么
- 一个最小的 http 函数,以演示如何使用 Rust 的本地 http 包与 API Gateway 交互(请注意,这将是直到 0.2 版本发布前的 git 依赖项)
- 一个组合 multi 函数服务,以演示如何设置具有多个独立函数的服务
假设您的宿主机具有相对较新的 node 版本,您不需要安装任何全局的 serverless 依赖项。要开始,运行以下命令创建一个新的 lambda Rust 应用程序并安装项目级依赖项。
$ npx serverless install \
--url https://github.com/softprops/serverless-aws-rust \
--name my-new-app \
&& cd my-new-app \
&& npm install --silent
使用标准的 serverless 工作流程部署它
# build, package, and deploy service to aws lambda
$ npx serverless deploy
使用 serverless 框架或配置的 AWS 集成触发源调用它
npx serverless invoke -f hello -d '{"foo":"bar"}'
2.5. Docker
或者,您可以在 AWS Lambda 提供的运行时 docker 镜像 中构建基于 Rust 的 Lambda 函数,其中已预先安装 Rust 工具链。
运行以下命令将启动一个短暂的Docker容器,该容器将构建您的Rust应用程序,并生成一个包含其二进制的zip文件,二进制文件自动重命名为bootstrap,以满足AWS Lambda对target/lambda_runtime/release/{your-binary-name}.zip下的二进制文件的要求。通常,如果您使用cargo默认的二进制文件(即main.rs),这将是您的crate名称。
# build and package deploy-ready artifact
$ docker run --rm \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/root/.cargo/registry \
-v ${HOME}/.cargo/git:/root/.cargo/git \
rustserverless/lambda-rust
您的应用程序构建和打包完毕后,就可以部署到生产环境。您还可以使用lambci提供的Docker容器在本地调用它以验证其行为,这个容器也是AWS Lambda提供运行时的镜像,省略了构建依赖项。
# start a docker container replicating the "provided" lambda runtime
# awaiting an event to be provided via stdin
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v /tmp/lambda:/var/task \
lambci/lambda:provided
# provide an event payload via stdin (typically a json blob)
# Ctrl-D to yield control back to your function
本地开发和测试
使用单元和集成测试测试您的代码
AWS Lambda事件是从JSON对象反序列化而成的普通结构。如果您函数的处理程序使用标准运行时,您可以使用serde将您的文本测试用例反序列化到结构中,并直接调用您的处理程序。
#[test]
fn test_my_lambda_handler() {
let input = serde_json::from_str("{\"command\": \"Say Hi!\"}").expect("failed to parse event");
let context = lambda_runtime::Context::default();
let event = lambda_runtime::LambdaEvent::new(input, context);
my_lambda_handler(event).await.expect("failed to handle event");
}
如果您使用lambda_http接收HTTP事件,您还可以从纯文本测试用例创建http_lambda::Request结构。
#[test]
fn test_my_lambda_handler() {
let input = include_str!("apigw_proxy_request.json");
let request = lambda_http::request::from_str(input)
.expect("failed to create request");
let response = my_lambda_handler(request).await.expect("failed to handle request");
}
Cargo Lambda
Cargo Lambda提供了一个本地服务器,它模拟了AWS Lambda的控制平面。该服务器适用于Windows、Linux和MacOS。在您的Lambda项目根目录下,您可以使用以下子命令编译您的函数并启动服务器。
cargo lambda watch -a 127.0.0.1 -p 9001
现在您可以使用cargo lambda invoke向您的函数发送请求。例如
cargo lambda invoke <lambda-function-name> --data-ascii '{ "command": "hi" }'
在HTTP函数(函数URL、API网关等)上运行该命令需要您使用适当的方案。您可以在这里找到这些方案的示例。否则,您将看到以下错误。
Error: serde_json::error::Error
× data did not match any variant of untagged enum LambdaRequest
一个更简单的替代方案是根据您定义的地址和端口curl以下端点。例如
curl -v -X POST \
'http://127.0.0.1:9001/lambda-url/<lambda-function-name>/' \
-H 'content-type: application/json' \
-d '{ "command": "hi" }'
警告不要删除
content-type头。这是必要的,用于指导函数如何反序列化请求体。
您可以在项目的文档页面上阅读更多关于cargo lambda watch和cargo lambda invoke的信息。
Lambda调试代理
您可以使用一个特殊的Lambda调试代理(由@rimutaka维护的非AWS仓库)在本地运行和调试Lambda,该代理是一个Lambda函数,它将传入的请求转发到一个AWS SQS队列,并从另一个队列读取响应。运行在您的开发计算机上的本地代理读取队列,调用本地的Lambda,并发送响应。这种方法允许在AWS工作流中本地调试Lambda函数,而无需在本地和AWS版本之间修改Lambda处理程序代码。
跟踪和日志记录
Lambda的Rust运行时与(跟踪)https://tracing.rs库集成,提供跟踪和日志记录功能。
默认情况下,运行时发出 tracing 事件,您可以通过 tracing-subscriber 收集这些事件。它还启用了一个名为 tracing 的功能,该功能公开了一个具有合理选项的默认订阅者,可以将日志信息发送到 AWS CloudWatch。请参考下面的示例,了解如何启用默认订阅者。
use lambda_runtime::{run, service_fn, tracing, Error};
#[tokio::main]
async fn main() -> Result<(), Error> {
tracing::init_default_subscriber();
run(service_fn(|event| tracing::info!(?event))).await
}
订阅者使用 RUST_LOG 作为环境变量来决定函数的日志级别。如果为您的函数配置了 Lambda 的高级日志控制功能,它还会使用 Lambda 的高级日志控制。默认情况下,发出事件的日志级别为 INFO。
AWS 事件对象
此项目包括 Lambda 事件结构定义,aws_lambda_events。此 crate 可以用于提供强类型 Lambda 事件结构。您还可以创建自己的自定义事件对象及其相应的结构。
自定义事件对象
为了序列化和反序列化事件和响应,我们建议使用 serde 库。为了接收自定义事件,请使用 Serde 的宏注解您的结构。
use serde::{Serialize, Deserialize};
use serde_json::json;
use std::error::Error;
#[derive(Serialize, Deserialize)]
pub struct NewIceCreamEvent {
pub flavors: Vec<String>,
}
#[derive(Serialize, Deserialize)]
pub struct NewIceCreamResponse {
pub flavors_added_count: usize,
}
fn main() -> Result<(), Box<Error>> {
let flavors = json!({
"flavors": [
"Nocciola",
"抹茶",
"आम"
]
});
let event: NewIceCreamEvent = serde_json::from_value(flavors)?;
let response = NewIceCreamResponse {
flavors_added_count: event.flavors.len(),
};
serde_json::to_string(&response)?;
Ok(())
}
lambda_http 中的功能标志
lambda_http 是 Amazon Load Balancer (ALB)、Amazon Api Gateway (APIGW) 和 AWS Lambda Function URLs 从三个不同服务接收 HTTP 事件的包装器。Amazon Api Gateway 还可以从三个不同的端点发送事件,即 REST APIs、HTTP APIs 和 WebSockets。lambda_http 将来自所有这些来源的事件转换为原生的 http::Request 对象,这样您就可以将 Rust HTTP 语义集成到 Lambda 函数中。
默认情况下,lambda_http 将您的函数编译为支持这些服务中的任何一种。这会增加函数的编译时间,因为我们必须为所有来源生成代码。实际上,您通常只将 Lambda 函数放在这些来源之一之后。您可以通过功能标志选择为哪个来源生成代码。
lambda_http 可用的功能标志如下:
alb:用于来自 Amazon Elastic Load Balancer 的事件。apigw_rest:用于来自 Amazon API Gateway Rest APIs 的事件。apigw_http:用于来自 Amazon API Gateway HTTP APIs 和 AWS Lambda Function URLs 的事件。apigw_websockets:用于来自 Amazon API Gateway WebSockets 的事件。
如果您只想支持这些来源之一,您可以在包的 Cargo.toml 文件中禁用默认功能,并仅启用您关心的来源。将 lambda_http 的依赖项行替换为下面的代码片段,更改要启用的功能。
[dependencies.lambda_http]
version = "0.5.3"
default-features = false
features = ["apigw_rest"]
这将使您的函数编译速度大大提高。
支持的 Rust 版本 (MSRV)
AWS Lambda Rust 运行时至少需要 Rust 1.66,并且不能保证在比这更早的编译器版本上构建。
安全
有关更多信息,请参阅 CONTRIBUTING。
许可证
本项目采用 Apache-2.0 许可证。
依赖项
~2.5MB
~63K SLoC