通过 HTTP API 暴露 Lambda 函数

AWSBeginner
立即练习

介绍

状态页面需要一个报告应用是否健康的 HTTP 端点。你将把提供的 Lambda 处理程序连接到 HTTP API,发送请求,诊断调用权限,并移除自己的资源。

请先完成 使用 JSON 事件运行 Lambda 函数 和 配置并诊断 Lambda 函数,包括它们的角色与日志先修内容。这个全新环境提供处理程序和执行角色。

部署健康检查函数

本步骤中,你将打包提供的健康检查处理程序,并部署一个能够响应 HTTP 事件的函数。

进入准备好的工作目录:

cd /home/labex/project

打开 Terminal 旁的 AWS View,观察与命令相同的函数、API 和日志状态。最初只有无关的参考日志;请保留它们。

打包之前先读取提供的应用:

cat app.py

处理程序接收事件,记录输入,并返回代理响应,其中包含 statusCode、headers 和 body 中的 JSON 字符串。HTTP 载荷格式 2.0 将 URL 查询参数放在 queryStringParameters 中。可选的 name 参数改变问候语。RELEASE_LABEL 是与问候语一同返回的环境设置。

使用 zip 将 app.py 放在部署归档文件的根目录:

zip health.zip app.py

将准备好的角色 ARN 读入 shell 变量。--query 选择一个响应字段,--output text 让下一条命令能够使用它:

ROLE_ARN=$(aws iam get-role --role-name labex-a01-execution --query 'Role.Arn' --output text)

使用 Python 3.12 和准备好的执行角色部署 app.handler。fileb:// 上传 Zip 字节。JSON Variables 映射使用与 Lambda 配置实验相同的格式。它的字符串值标记首次发布:

aws lambda create-function \
  --function-name labex-a01-health \
  --runtime python3.12 \
  --role "$ROLE_ARN" \
  --handler app.handler \
  --timeout 5 \
  --environment '{"Variables":{"RELEASE_LABEL":"initial"}}' \
  --zip-file fileb://health.zip \
  --query '{Name:FunctionName,Handler:Handler,Runtime:Runtime}'

响应应标明 labex-a01-health、app.handler 和 python3.12。打开 AWS View,检查 Function 卡片。仅部署函数还不能提供 HTTP 路由;HTTP APIs 卡片仍为空。

连接 HTTP 路由并发送请求

本步骤中,你将把 HTTP 请求连接到已部署的函数。Amazon API Gateway 提供 HTTP 入口。路由根据方法和路径(例如 GET /health)选择后端集成。

创建 HTTP API,将生成的 ID 保存到 shell 变量。命令替换 $(...) 会捕获选中的 API ID,而不是显示它:

API_ID=$(aws apigatewayv2 create-api --name labex-a01 --protocol-type HTTP --query ApiId --output text)

记录这个 ID,作为资源清单的一部分。重定向 > 将值写入文件:

printf '%s\n' "$API_ID" > api-id.txt

阶段(stage)是 API 的部署入口。$default 阶段的 URL 不包含阶段名称路径段。--auto-deploy 自动应用更改。单引号保留字面意义上的美元符号:

aws apigatewayv2 create-stage --api-id "$API_ID" --stage-name '$default' --auto-deploy --query '{Stage:StageName,AutoDeploy:AutoDeploy}'

读取已部署的函数 ARN,再创建 AWS_PROXY 集成。Lambda 集成使用 POST 调用后端,即使下方传入的客户端路由使用 GET。载荷格式 2.0 与提供的处理程序匹配:

FUNCTION_ARN=$(aws lambda get-function-configuration --function-name labex-a01-health --query FunctionArn --output text)
INTEGRATION_ID=$(aws apigatewayv2 create-integration --api-id "$API_ID" --integration-type AWS_PROXY --integration-method POST --integration-uri "$FUNCTION_ARN" --payload-format-version 2.0 --query IntegrationId --output text)

路由键组合客户端 HTTP 方法与路径。它的目标指向刚创建的集成:

aws apigatewayv2 create-route \
  --api-id "$API_ID" \
  --route-key 'GET /health' \
  --target "integrations/$INTEGRATION_ID" \
  --authorization-type NONE \
  --query '{Route:RouteKey,Authorization:AuthorizationType}'

这个公开健康检查路由使用 NONE;应用登录将在后续介绍。执行角色控制函数代码能做什么,函数的资源策略则控制谁能调用它。API Gateway 仍需要准确的调用授权。

读取所选账户 ID,并构造这个 API 默认阶段的 GET /health 路由来源 ARN。转义的美元符号在展开字符串时保留字面意义上的 $default:

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
SOURCE_ARN="arn:aws:execute-api:us-east-1:$ACCOUNT_ID:$API_ID/\$default/GET/health"

仅授予这个 API 路由调用函数的权限:

aws lambda add-permission \
  --function-name labex-a01-health \
  --statement-id ApiHealth \
  --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com \
  --source-account "$ACCOUNT_ID" \
  --source-arn "$SOURCE_ARN" \
  --query Statement \
  --output text

在这个工作环境中发送 HTTP 请求时,使用准备好的 API 地址和生成的 API ID。这是工作环境的 API 入口,不是 AWS 公共主机名:

API_URL="http://127.0.0.1:8081/api/$API_ID"

官方 Console 显示相同的 API ID、$default 阶段和 Auto deploy 设置。它的 Invoke URL 是 AWS 端点;本实验继续使用上方工作环境的 API_URL。

官方 API Gateway Console 显示 API 详情和默认阶段的调用 URL

来源:AWS API Gateway。

curl -i 同时显示 HTTP 响应头和响应体。URL 查询参数会成为实际 Lambda 事件的一部分:

curl -i "$API_URL/health?name=Maya"

预期得到 HTTP 200 和以下 JSON 响应体:

{"healthy": true, "message": "Hello, Maya", "release": "initial"}

返回 AWS View。HTTP APIs 卡片应显示 GET /health、NONE 和 $default · AutoDeploy true。CloudWatch Logs 卡片应显示实际路由、状态和响应。点击 Show logs,找到包含 name: Maya 的 queryStringParameters。这项手动观察将 HTTP 请求与已部署函数的输入联系起来;验证检查远端配置和实际执行。

AWS View 中的 HTTP 健康检查路由及其 Lambda 响应

这个示例显示已配置的路由及其成功的 Maya / initial 响应。你生成的 API ID 和代码指纹会有所不同。

健康检查路由为请求选择 Lambda 集成。

诊断调用权限并发布新版本标记

本步骤中,你将观察失效的调用边界,恢复准确的授权,并测试更改后的函数设置。

通过语句 ID 移除授权。API、集成和执行角色仍然保留:

aws lambda remove-permission --function-name labex-a01-health --statement-id ApiHealth

授权不存在时,再发送一个请求:

curl -i "$API_URL/health?name=Noah"

预期得到 HTTP 502 和 Invocation permission denied。API 部署和路由配置本身不会授予 Lambda 调用权限。在 AWS View 中,已有成功调用仍然保留;这个被拒绝的请求没有运行处理程序。手动比较请求前后的日志。自动检查不会根据最终恢复的策略推断历史上曾发生拒绝。

恢复相同的账户和路由限定授权:

aws lambda add-permission \
  --function-name labex-a01-health \
  --statement-id ApiHealth \
  --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com \
  --source-account "$ACCOUNT_ID" \
  --source-arn "$SOURCE_ARN" \
  --query Statement \
  --output text

更改函数环境,以标记 ready 发布状态。处理程序运行时读取这个设置:

aws lambda update-function-configuration --function-name labex-a01-health --environment '{"Variables":{"RELEASE_LABEL":"ready"}}' --query 'Environment.Variables'

路由仍指向同一个函数。使用不同的查询值发送请求:

curl -i "$API_URL/health?name=Noah"

预期得到 HTTP 200,响应由新的查询值和环境设置共同计算:

{"healthy": true, "message": "Hello, Noah", "release": "ready"}

在 AWS View 中检查最新响应,并展开日志。确认输入为 Noah,响应体包含 ready。较早的 Maya 响应应仍可查看。这些不同结果证明集成运行了已部署函数,而非返回单一固定的健康检查消息。

删除你的 API 和函数

本步骤中,你将移除创建的资源,并证明无关的参考日志得到保留。

你的资源清单包括 api-id.txt 中的 API ID、labex-a01-health 和 /aws/lambda/labex-a01-health。API 管理自己的路由、集成和默认阶段。先删除 API,使它无法再接收请求:

aws apigatewayv2 delete-api --api-id "$API_ID"

移除函数及其调用策略:

aws lambda delete-function --function-name labex-a01-health

Lambda 日志组具有自己的生命周期。仅删除这个函数的日志组:

aws logs delete-log-group --log-group-name /aws/lambda/labex-a01-health

成功读取原生资源清单;请求错误不能证明删除完成:

aws apigatewayv2 get-apis --query 'Items[].Name'
aws lambda list-functions --query 'Functions[].FunctionName'

两个列表都应为空。读取剩余的日志组:

aws logs describe-log-groups --query 'logGroups[].logGroupName'

应只剩下 /labex/labex-a01-reference。保留它和准备好的执行角色。在 AWS View 中确认 API、Function 和调用卡片为空,而 Reference logs 仍显示 INFO platform reference keep unchanged。

总结

你部署了 Python 健康检查处理程序,通过载荷 2.0 集成连接 HTTP API 路由,并启用了默认阶段。你限定了 API 的 Lambda 调用授权,诊断了移除授权后的行为,并观察实际查询值和函数设置产生的不同响应。最后,你移除了自己的 API、函数和日志组,同时保留了无关资源。