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