rust的aws sdk
参考资料
- https://docs.aws.amazon.com/sdk-for-rust/latest/dg/getting-started.html
- https://awslabs.github.io/aws-sdk-rust/
- https://github.com/awslabs/aws-sdk-rust
- https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rust_dev_preview
rus sdk获取凭证的顺序
- Environment variables:
AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
, andAWS_REGION
- The default credentials files located in
~/.aws/config
and~/.aws/credentials
(location can vary per platform) - Web Identity Token credentials from the environment or container (including EKS)
- ECS Container Credentials (IAM roles for tasks)
- EC2 Instance Metadata Service (IAM Roles attached to instance)
以下是示例的列出s3桶代码
// Cargo.toml
[package]
name = "rusttour"
version = "0.1.0"
edition = "2021"
[dependencies]
aws-config = "0.54.1"
aws-sdk-s3 = "0.24.0"
structopt = "0.3.26"
tokio = { version = "1.25.0", features = ["full"] }
tracing-subscriber = "0.3.16"
// main.rs
use aws_config::meta::region::RegionProviderChain;
use aws_sdk_s3::{Client, Error, Region, PKG_VERSION};
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
struct Opt {
#[structopt(short, long)]
region: Option<String>,
#[structopt(short, long)]
bucket: String,
#[structopt(short, long)]
verbose: bool,
}
async fn show_objects(client: &Client, bucket: &str) -> Result<(), Error> {
let resp = client.list_objects_v2().bucket(bucket).send().await?;
for object in resp.contents().unwrap_or_default() {
println!("{}", object.key().unwrap_or_default());
}
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Error> {
tracing_subscriber::fmt::init();
let Opt {
region,
bucket,
verbose,
} = Opt::from_args();
let region_provider = RegionProviderChain::first_try(region.map(Region::new))
.or_default_provider()
.or_else(Region::new("cn-north-1"));
println!();
if verbose {
println!("S3 client version: {}", PKG_VERSION);
println!(
"Region: {}",
region_provider.region().await.unwrap().as_ref()
);
println!("Bucket: {}", &bucket);
println!();
}
let shared_config = aws_config::from_env().region(region_provider).load().await;
let client = Client::new(&shared_config);
show_objects(&client, &bucket).await
}
lambda的rust自定义运行时
lambda自定义运行时
lambda自定义运行时是一个比较复杂的话题
运行时是一个程序,调用函数时程序将运行 Lambda 函数的处理程序方法。可以采用可执行文件(名为
bootstrap
)的形式, 将运行时包含在函数的部署程序包中
自定义运行时的入口点是一个名为 bootstrap
的可执行文件。引导文件可以是运行时,也可以调用创建运行时的另一个文件。运行时代码负责完成一些初始化任务。然后,它将在一个循环中处理调用事件直到被终止
(1)初始化任务
- 检索设置 – 读取环境变量以获取有关函数和环境的详细信息。
_HANDLER
– 处理程序的位置(来自函数的配置)。标准格式为file.method
,其中file
是没有表达式的文件的名称,method
是在文件中定义的方法或函数的名称。LAMBDA_TASK_ROOT
– 包含函数代码的目录。AWS_LAMBDA_RUNTIME_API
– 运行时 API 的主机和端口。- 初始化函数 – 加载处理程序文件并运行它包含的任何全局或静态代码。函数应该创建静态资源(如开发工具包客户端和数据库连接)一次,然后将它们重复用于多个调用。
- 处理错误 – 如果出现错误,请调用初始化错误 API 并立即退出。
(2)处理任务
- 获取事件 – 调用下一个调用 API 来获取下一个事件。响应正文包含事件数据。响应标头包含请求 ID 和其他信息。
- 传播跟踪标头 – 从 API 响应中的
Lambda-Runtime-Trace-Id
标头获取 X-Ray 跟踪标头。使用相同的值在本地设置_X_AMZN_TRACE_ID
环境变量。X-Ray SDK 使用此值在服务之间连接追踪数据。- 创建上下文对象 – 使用来自 API 响应中的环境变量和标头的上下文信息创建一个对象。
- 调用函数处理程序 – 将事件和上下文对象传递到处理程序。
- 处理响应 – 调用调用响应 API 以发布来自处理程序的响应。
- 处理错误 – 如果出现错误,请调用调用错误 API。
- 清理 – 释放未使用的资源,将数据发送到其他服务,或在获取下一个事件之前执行其他任务。
官方提供了一个自定义运行时的示例
Tutorial – Publishing a custom runtime
创建rust运行时函数
https://docs.aws.amazon.com/sdk-for-rust/latest/dg/lambda.html
https://github.com/awslabs/aws-lambda-rust-runtime#deployment
lambda托管环境目前没有对rust运行时的支持,因此无法直接创建。aws-lambda-rust-runtime
仓库提供了构建自定义lambda运行时的方式。
使用cargo-lambda
可以快速在本地创建rust运行时的lambda函数
https://www.cargo-lambda.info/guide/installation.html
pip3 install cargo-lambda
创建新的lambda项目
$ cargo lambda new myrustlambda
查看项目配置
$ cat Cargo.toml
[package]
name = "myrustlambda"
version = "0.1.0"
edition = "2021"
[dependencies]
lambda_runtime = "0.7"
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"] }
创建示例的lambda函数
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) }))
}
构建函数,当然还可以交叉编译为其他平台,默认情况CargoLambda 将构建在 x86 _ 64架构上运行的函数
$ cargo lambda build --release
$ # cargo lambda build --release --arm64
$ #cargo lambda build --release --target aarch64-unknown-linux-gnu.2.17
构建过程中出现以下错误
warning: spurious network error (2 tries remaining): [28] Timeout was reached
修改下载源为tuna
# `$HOME/.cargo/config`
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'tuna'
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"
[net]
git-fetch-with-cli=true
对于自定义运行时,AWS Lambda 在部署包 zip 中查找名为 bootstrap 的可执行文件。在 target/lambda 目录下找到函数的引导程序二进制文件
$ tree -L 3
├── Cargo.lock
├── Cargo.toml
├── src
│ └── main.rs
└── target
├── CACHEDIR.TAG
├── lambda
│ └── myrustlambda //引导程序
├── bootstrap.zip
└── bootstrap
├── release
│ ├── build
│ ├── deps
│ ├── examples
│ └── incremental
└── x86_64-unknown-linux-gnu
├── CACHEDIR.TAG
└── release
部署函数
$ cargo lambda deploy \
--iam-role arn:aws-cn:iam::037047667284:role/myLambdaRole
将函数打包为zip查看具体的内容,压缩包中只有一个bootstrap二进制文件
cargo lambda build --release --output-format zip
测试函数
$ aws lambda invoke \
--cli-binary-format raw-in-base64-out \
--function-name myrustlambda \
--payload '{"command": "Say Hi!"}' \
output.json
$ cat output.json
{"message":"Hello, world!"}