#aws-lambda #lambda #aws #http #serverless #http-interface

lando

Rust语言对AWS Lambda API网关事件的HTTP接口

6个版本

使用旧的Rust 2015

0.2.1 2018年11月28日
0.2.0 2018年11月28日
0.1.1 2018年6月6日
0.0.1 2018年6月4日
0.0.0 2018年5月25日

#23 in #http-interface

22每月下载量

MIT许可证

44KB
884

lando 构建状态 覆盖率状态 crates.io docs.rs Master API文档

Rustlang上运行HTTP应用程序,使用AWS LambdaAPI网关

#[macro_use] extern crate lando;

gateway!(|_, _| {
  Ok("👋 Hello, what have we here?")
});

🤔 关于

Lando是一个用于构建无服务器Rustlang HTTP应用程序的包。

Rust语言生态系统有一些非常好的HTTP服务器包。其中大多数都捆绑了服务器,这些服务器可以解析HTTP消息、监听端口并管理网络连接,而将托管、扩展、监控和操作的责任留给了你,这些操作除了你的应用程序代码之外。

Lando与众不同。Lando的唯一重点是编写应用程序。它将管理服务器的责任转移给了AWS。更直接地说,AWS Lambda让你可以运行代码,而不必考虑服务器。

Lando 采用了 Rust 社区中 httpcrate 作为其核心接口,用于 API 网关。Lando 扩展了 crowbarcrate 的现有功能,该crate提供了部署 Rust 应用程序所需的底层机制,支持 lambda 的 最低开销运行时之一,Python 3.6。Lando 面向由 API 网关触发的 lambda。如果您为 Lambda 的许多其他触发器构建应用程序,请查看 crowbar

目前存在一个庞大且成熟的 AWS Lambda 工具生态系统,并且运行良好,包括如 serverless 工具包之类的流程工具。由于这些工具很可能已经存在于组织内部,引入 Rustlang 到它们的武器库中的障碍将会大大降低。Lando 并不打算取代这些工具,而是希望与它们良好地协同工作 👫🏾。

👍 为什么 Rust 是 Lambda 应用的好选择

AWS Lambda 的 成本模型主要基于两个因素:内存大小和速度。提供给应用程序的 CPU 与请求的内存大小成正比。Lambda 具有按使用付费的成本模型,优先考虑既快速又具有低内存开销的应用程序。

作为一种系统语言,Rust 被专门设计来满足这类需求。Rust 具有非常 小巧的运行时,内存管理 非常高效,且 非常快速

作为一种高度可嵌入的语言,其与 Python 等运行时的互操作性故事 💖。请注意,Lando 假设您通过 AWS API 网关公开这些应用程序,该网关具有自己的 慷慨定价模型

📦 安装

将以下内容添加到您的 cargo 项目中的 Cargo.toml 文件。

[lib]
crate-type = ["cdylib"]

[dependencies]
lando = "0.2"

💡 crate-type 属性 链接 并生成一个共享对象( *.so )文件,允许您的 Rustlang 应用程序编译为可以在 AWS Python 3.6 lambda 运行时中调用的 Linux 原生二进制文件。

👩‍🏭 创建

Lando 导出了一个名为 gateway! 的宏,该宏又导出了一个 Rust 函数或闭包到 cpython 原生二进制扩展,使其可以在 AWS Lambda 中使用。

#[macro_use] extern crate lando;

gateway!(|request, _context| {
  println!("{:?}", request);
  Ok("hello lambda")
});

此闭包接受一个带有 lando::Bodyhttp::Request。如果需要,此 Body 类型可以解引用为字节数组。

有关更多详细信息,请参阅此项目的 crate 文档

Lando 还支持将函数作为 lambda 准备好的 fn 导出的函数属性方法。

#[macro_use] extern crate lando;
use lando::{Request, LambdaContext, IntoResponse, Result};

#[lando]
fn example(
  _: Request,
  _: LambdaContext
) -> Result<impl IntoResponse> {
   Ok("hello lambda")
}

🔬 测试

由于这些函数只是 Rust,您可以使用内置的单元测试框架测试您的应用程序。

此外,您还可以通过本地调用它们来集成测试您的函数。

🐳 Lambda CI

包含与 AWS Lambda 运行时镜像的 lambda CI docker 项目。这使得您可以在与 AWS 相匹配的本地环境中构建和测试您的 lambda 项目。

构建

为了在 Lambda 兼容的环境中调用您的函数,您必须首先在其中一个环境中构建它。

$ docker run --rm \
  -v ${PWD}:/code \
  -v ${HOME}/.cargo/registry:/root/.cargo/registry \
  -v ${HOME}/.cargo/git:/root/.cargo/git \
  -e CARGO_FLAGS="--features lando/python3-sys" \
  softprops/lambda-rust

这将在target/lambda/release目录下生成一个本地的Linux二进制.so文件

调用

您可以使用lambci/lambda:python3.6的Docker镜像在本地调用您的lambda

此示例通过管道传递一个文件(在这个例子中是一个名为example_request.json的文件)来提供lambda的事件,尽管是通过标准输入。请随意创建您自己的模拟输入。

cat example_request.json
{
  "path": "/test/hello",
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, lzma, sdch, br",
    "Accept-Language": "en-US,en;q=0.8",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-Country": "US",
    "Host": "wt6mne2s9k.execute-api.us-west-2.amazonaws.com",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
    "Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)",
    "X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==",
    "X-Forwarded-For": "192.168.100.1, 192.168.1.1",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "pathParameters": {
    "proxy": "hello"
  },
  "requestContext": {
    "accountId": "123456789012",
    "resourceId": "us4z18",
    "stage": "test",
    "requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9",
    "identity": {
      "cognitoIdentityPoolId": "",
      "accountId": "",
      "cognitoIdentityId": "",
      "caller": "",
      "apiKey": "",
      "sourceIp": "192.168.100.1",
      "cognitoAuthenticationType": "",
      "cognitoAuthenticationProvider": "",
      "userArn": "",
      "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
      "user": ""
    },
    "resourcePath": "/{proxy+}",
    "httpMethod": "GET",
    "apiId": "wt6mne2s9k"
  },
  "resource": "/{proxy+}",
  "httpMethod": "GET",
  "queryStringParameters": {
    "name": "me"
  },
  "stageVariables": {
    "stageVarName": "stageVarValue"
  }
}

使用docker调用生成的函数,提供模拟事件的上下文作为stdin。

$ docker run \
  -i -e DOCKER_LAMBDA_USE_STDIN=1 \
  --rm \
  -v \
  "$PWD/target/lambda/release":/var/task lambci/lambda:python3.6 \
  liblambda.handler < example_request.json

🚀 部署

为了部署您的应用,您需要在与lambda Python 3.6环境兼容的运行时中构建它。

⚡ 无服务器框架

推荐的开始方式是使用无服务器框架。存在一个无服务器框架插件,用于加速开发/部署周期。

您可以使用这个无服务器项目模板来启动一个新部署就绪的lando应用程序。

$ serverless install \
  --url https://github.com/softprops/serverless-lando \
  --name my-new-service

🐳 Docker

提供了一个方便的Docker镜像,该镜像复制了AWS Python3.6环境,并带有Rustlang构建工具。

它主要针对Rust的稳定版本的应用。

$ docker run --rm \
  -v ${PWD}:/code \
  -v ${HOME}/.cargo/registry:/root/.cargo/registry \
  -v ${HOME}/.cargo/git:/root/.cargo/git \
  -e CARGO_FLAGS="--features lando/python3-sys" \
  softprops/lambda-rust

这将在target/lambda目录下生成一个可部署的.so构建工件。

然后可以将其打包用于AWS Lambda部署。

🏃 性能

对于lambda应用程序或任何应用程序的性能分析,都取决于您的用例。在lando的具体情况下,因素包括

  • 您使用的API网关(AWS运行的HTTP负载均衡器,调用您的函数)
  • 您的lambda配置(内存分配和连接到VPC等资源)
  • lambda转换层(在Python和Rust之间转换)
  • 您的应用程序(也就是您!)

无服务器思维模式是控制运行时与应用程序关注之间的显式权衡。

您的应用程序可以在十位数毫秒内运行。

Lando的目标是在本地的Python事件到本地的Rustlang HTTP类型之间以及返回提供一个最小侵入性的转换层

存在一个基准测试来测量使用典型的网关事件的转换时间,该事件报告典型的(8.65 μ(微)秒结果 +/- 4 μ秒)。这不太可能是您应用程序的瓶颈

test gateway_conversion ... bench:       8,652 ns/iter (+/- 4,193)

💱 并发性

在接近AWS Lambda的性能时,应考虑并发性。

AWS Lambda明确是水平扩展的。您不是通过在运行进程中生成了更多的线程(向上扩展 ↕️)来扩展,而是通过生成更多的lambda(向外扩展 ↔️)来扩展。

AWS Lambda的一个关键好处是平台通过为您生成您函数的更多实例来处理并发。这导致了一些经济优势,您只需要为所使用的付费。请注意,您按照每100毫秒的间隔计费,因此一旦低于这一点,优化成本的有用性就会丧失

现实世界的例子

  • slack standup 自动化站立会议的slack命令webhook
  • jirabars 根据分支名称填充jira占位符信息的github webhook
  • barbershop 在pr后删除分支的github webhook

🚧 计划中的更改

(无)

Doug Tangren (softprops) 2018

依赖关系

~7MB
~167K SLoC