AWS Lambda Function
是轻量级的计算服务。优势是按需付费,专注于功能,服务本身如何构建暴露都有AWS
都不需要自己操心。
而按需付费基本就是服务使用时长和内存占用了,这个优化的话那妥妥的是Rust
的拿手好戏, 所以现在有好多Serverless
服务都用Rust
构建的Lambda Function
来搞。
今天简单看下如何用Rust
快速构建Lambda Function
(别担心没aws环境,往下看,有本地沙箱可尝试)
cargo-lambda cargo-lambda
这个库可以用来构建Lambda Function
(也是官方推荐的工具)
如下代码安装:
1 2 brew tap cargo-lambda/cargo-lambda brew install cargo-lambda
然后初始化一个demo
1 2 cargo lambda new lambda-demo > Is this function an HTTP function ? Yes
会自动生成初始化项目,引入相关依赖及运行时:lambda-http
和tokio
依赖
功能部分代码如下,提供一个hello world
式请求处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 use lambda_http::{run, service_fn, tracing, Body, Error, Request, RequestExt, Response};async fn function_handler (event: Request) -> Result <Response<Body>, Error> { let who = event .query_string_parameters_ref() .and_then(|params| params.first("name" )) .unwrap_or("world" ); let message = format! ("Hello {who}, this is an AWS Lambda HTTP request" ); let resp = Response::builder() .status(200 ) .header("content-type" , "text/html" ) .body(message.into()) .map_err(Box ::new)?; Ok (resp) } #[tokio::main] async fn main () -> Result <(), Error> { tracing::init_default_subscriber(); run(service_fn(function_handler)).await }
题外话,有没有感觉这个service_fn
很眼熟?
这个接的handler
也要求实现Service trait
, 跟tower service
一样。为啥呢,用了hyper
库! 都说hyper
基本就是Rust
服务框架的基石不假。
运行 开发中用watch
就能本地运行调试,支持变更重编译
1 2 cargo lambda watch # INFO invoke server listening on [::]:9000
也可以命令行调用
1 cargo lambda invoke lambda-demo --data-ascii "?name=newbmiao"
打包 1 cargo lambda build --release --arm64
这样会将执行文件编译到./target/lambda/lambda-demo/bootstrap
(注意:如果是workspace
, 则需要去workspace
下target
目录找)
可执行文件压缩一下就可以用来部署了
1 zip bootstrap.zip bootstrap
部署 (这部分会设计比较多infrastructure,感兴趣的同学可以继续往下)
部署也很方便,不过难在不是所有人都有aws
账户啊。
也好解决,localstack
可以本地模拟aws
环境
用docker-compose up
起个localstack
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 version: "3.8" services: localstack: container_name: "${LOCALSTACK_DOCKER_NAME:-localstack-main}" image: localstack/localstack ports: - "127.0.0.1:4566:4566" - "127.0.0.1:4510-4559:4510-4559" environment: - DEBUG=${DEBUG:-0 } volumes: - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" - "/var/run/docker.sock:/var/run/docker.sock"
然后用terraform
构建部署流程, 核心部分就是:
1 2 3 4 5 6 7 8 9 10 # 构建 resource "aws_lambda_function" "lambda_demo" { filename = "bootstrap.zip" function_name = "lambda_demo" role = aws_iam_role.iam_for_lambda_tf.arn handler = "bootstrap" source_code_hash = filebase64sha256("bootstrap.zip") runtime = "provided.al2" architectures = ["arm64"] }
剩下就是权限以及获取lambda function
地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 resource "aws_lambda_function_url" "lambda_demo_url" { function_name = aws_lambda_function.lambda_demo.arn authorization_type = "NONE" } output "function_url" { description = "Function URL." value = aws_lambda_function_url.lambda_demo_url.function_url } resource "aws_iam_role" "iam_for_lambda_tf" { name = "iam_for_lambda_tf" assume_role_policy = <<EOF { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "lambda.amazonaws.com" }, "Effect": "Allow", "Sid": "" } ] } EOF }
这样从terraform apply
部署结果中能拿到访问地址, 比如
1 2 3 4 5 6 ... Apply complete! Resources: 3 added, 0 changed, 0 destroyed. Outputs: function_url = "http://h6v7ozz6ay3h6apr2hi5edsmnc0wpz80.lambda-url.us-east-1.localhost.localstack.cloud:4566/
想上手试下的话,详细代码见lambda-demo , build.sh
有详细打包流程
如有疑问,请文末留言交流或邮件:newbvirgil@gmail.com
本文链接 : https://newbmiao.github.io/2024/03/10/rust-lambda.html