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每月下载量
44KB
884 行
lando
在Rustlang上运行HTTP应用程序,使用AWS Lambda和API网关
#[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::Body 的 http::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