#aws-lambda #api-gateway #lambda #aws #serde-json #alb #load-balancer

fishrock_lambda_http

AWS Lambda 的应用程序负载均衡器和 API Gateway 事件类型

1 个不稳定版本

0.3.0-patched.12021 年 5 月 20 日

#553HTTP 服务器


2 个 Crates 中使用 (通过 tide-lambda-listener)

Apache-2.0

115KB
2.5K SLoC

Rust Runtime for AWS Lambda

Build Status

此包简化了用 Rust 编写的 AWS Lambda 函数的运行。此工作区包括多个 Crates

  • 文档 lambda-runtime 是一个库,为用 Rust 编写的应用程序提供 Lambda 运行时。
  • 文档 lambda-http 是一个库,使您能够轻松地在 Rust 中编写以 API Gateway 代理事件为重点的 Lambda 函数。

示例函数

下面的代码创建了一个简单的函数,它接收一个包含 firstName 字段的事件,并向调用者返回一条消息。注意:此 crate 对最新稳定版本的 Rust 进行了测试。

use lambda_runtime::{handler_fn, Context, Error};
use serde_json::{json, Value};

#[tokio::main]
async fn main() -> Result<(), Error> {
    let func = handler_fn(func);
    lambda_runtime::run(func).await?;
    Ok(())
}

async fn func(event: Value, _: Context) -> Result<Value, Error> {
    let first_name = event["firstName"].as_str().unwrap_or("world");

    Ok(json!({ "message": format!("Hello, {}!", first_name) }))
}

上面的代码与 lambda_runtime crate 中的 基本示例 相同。

部署

目前有几种构建此包的方法:手动使用 AWS CLI 和使用 Serverless 框架

AWS CLI

要使用 AWS CLI 将基本示例作为 Lambda 函数部署,我们首先需要使用 cargo 手动构建它。由于 Lambda 使用 Amazon Linux,您需要为目标可执行文件指定 x86_64-unknown-linux-musl 平台。

运行此脚本一次以添加新目标

$ rustup target add x86_64-unknown-linux-musl
  • 注意:如果您正在运行 Mac OS,则需要为目标平台安装链接器。您可以使用来自 Homebrewmusl-cross tap 来执行此操作,它为 Mac OS 提供了一个完整的交叉编译工具链。一旦安装了 musl-cross,我们还需要在构建 x86_64-unknown-linux-musl 平台时通知 cargo 新安装的链接器。
$ brew install filosottile/musl-cross/musl-cross
$ mkdir .cargo
$ echo $'[target.x86_64-unknown-linux-musl]\nlinker = "x86_64-linux-musl-gcc"' > .cargo/config

编译示例之一,将其编译为 发布 版本,以便部署到 AWS

$ cargo build -p lambda_runtime --example basic --release --target x86_64-unknown-linux-musl

对于 自定义运行时,AWS Lambda 会在部署包 zip 中查找名为 bootstrap 的可执行文件。将生成的 basic 可执行文件重命名为 bootstrap 并将其添加到 zip 归档中。

$ cp ./target/x86_64-unknown-linux-musl/release/examples/hello ./bootstrap && zip lambda.zip bootstrap && rm bootstrap

现在我们有了部署包(lambda.zip),我们可以使用 AWS CLI 创建一个新的 Lambda 函数。请确保用您账户中现有的角色替换执行角色!

$ aws lambda create-function --function-name rustTest \
  --handler doesnt.matter \
  --zip-file fileb://./lambda.zip \
  --runtime provided \
  --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 --function-name rustTest \
  --payload '{"firstName": "world"}' \
  output.json
$ cat output.json  # Prints: {"message": "Hello, world!"}

注意:使用 AWS CLI 版本 2 时,--cli-binary-format raw-in-base64-out 是必选参数。更多信息

Serverless Framework

或者,您可以使用 Serverless framework Rust 插件 声明性地构建基于 Rust 的 Lambda 函数。

存在许多入门 Serverless 应用程序模板,可以帮助您快速启动

  • 一个最小的 echo 函数,演示最小的 Rust 函数设置是什么样的
  • 一个最小的 http 函数,演示如何使用 Rust 的原生 http 包与 API Gateway 交互(注意这将是 git 依赖项,直到 0.2 发布)
  • 一个组合 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 framework 或配置的 AWS 集成触发源调用它

$ npx serverless invoke -f hello -d '{"foo":"bar"}'

Docker

或者,您可以在 AWS Lambda 提供的运行时 docker 映射中构建基于 Rust 的 Lambda 函数,预安装 Rust 工具链。

运行以下命令将启动一个临时的 docker 容器,该容器将构建您的 Rust 应用程序并生成一个 zip 文件,其中包含其二进制文件自动重命名为 bootstrap,以满足 AWS Lambda 对二进制文件的要求,通常这仅是您的 crate 名称,如果您使用的是 cargo 默认二进制(即 main.rs

# 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 \
    softprops/lambda-rust

当您的应用程序构建并打包后,即可部署到生产环境。您还可以使用lambdaci:提供的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

调试

Lambda函数可以在本地运行和调试,使用一个特殊的Lambda调试代理(由@rimutaka维护的非AWS仓库),这是一个Lambda函数,它将传入的请求转发到一个AWS SQS队列,并从另一个队列读取响应。运行在您开发计算机上的本地代理读取队列,调用您的Lambda函数并返回响应。这种方法允许在AWS工作流程中本地调试Lambda函数,而无需修改本地和AWS版本之间的lambda处理程序代码。

lambda

lambda_runtime是一个用于编写可靠和性能优良的基于Rust的AWS Lambda函数的库。从高层次来看,它提供了一些主要组件

  • Handler,一个定义客户编写的代码与该库之间交互的特质。
  • lambda_runtime::run,运行Handler的函数。

函数handler_fn将Rust函数或闭包转换为Handler,然后可以由lambda_runtime::run运行。

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(())
}

依赖项

~6.5–9MB
~155K SLoC