【免费下载链接】aws-cdk-examples
Example projects using the AWS CDK
导读
本文以aws-cdk-examples仓库中的 go/rekognition-lambda-s3-trigger 示例为主线,系统讲解如何用 AWS CDK(Go 语言)搭建一条"对象存储 → 事件触发 → AI 图像识别 → 结果落库"的完整链路。读完本文,你将掌握 CDK 基础设施代码(S3、DynamoDB、Lambda、IAM、事件通知)与 Lambda 处理器(RekognitionDetectLabels调用、DynamoDB 写入)的完整实现,并能直接cdk deploy部署验证。
架构与工作原理
该示例在 AWS 账户中创建以下资源(源自 README 的 "How it works" 一节):
- S3 存储桶:用于存放待识别的图片对象;
- DynamoDB 表:存储 Rekognition 识别出的标签(labels)结果;
- Lambda 函数:当新图片上传到 S3 时被自动触发,调用 AWS Rekognition 执行图像分类(标签识别);
- 角色与策略(Roles and Policies):为上述资源之间的访问授予最小必要权限;
- Rekognition 标签结果:被写入 DynamoDB 表。
整体数据流为:开发者通过 AWS CLI 或 SDK 向 S3 上传.jpg/.jpeg/.png图片 → S3 产生OBJECT_CREATED事件通知 → Lambda 被触发 → Lambda 用 AWS SDK 调用 RekognitionDetectLabels识别图片中的物体/场景标签 → 将"图片名 + 标签列表"写入 DynamoDB 表。
基础设施代码解析:CDK Go 栈
核心栈定义位于 rekognition-lambda-s3-trigger.go,入口main()通过awscdk.NewApp创建应用并合成RekognitionLambdaS3TriggerStack。env()函数返回nil,表示按默认账户/区域部署(由环境变量或本地配置决定)。
1. 创建 S3 存储桶
// Create S3 Bucket bucket := awss3.NewBucket(stack, jsii.String("Bucket"), &awss3.BucketProps{ RemovalPolicy: awscdk.RemovalPolicy_DESTROY, })RemovalPolicy_DESTROY表示删除栈(cdk destroy)时一并删除桶,适合示例/开发环境;生产环境建议改为RETAIN防止误删数据。
2. 创建 DynamoDB 表
// Create DynamoDb table table := awsdynamodb.NewTable(stack, jsii.String("Classifications"), &awsdynamodb.TableProps{ PartitionKey: &awsdynamodb.Attribute{ Name: jsii.String("image_name"), Type: awsdynamodb.AttributeType_STRING, }, RemovalPolicy: awscdk.RemovalPolicy_DESTROY, })- 表逻辑 ID 为
Classifications,分区键image_name(字符串类型),对应每个 S3 对象的 key; - 默认按需计费(on-demand)计费模式,未显式配置
BillingMode时使用默认值,对于低频演示场景足够。
3. 创建 Go Lambda 函数(含本地打包)
//Create Lambda function function := awscdklambdagoalpha.NewGoFunction(stack, jsii.String("main"), &awscdklambdagoalpha.GoFunctionProps{ Runtime: awslambda.Runtime_PROVIDED_AL2023(), Entry: jsii.String("./lambda-handler"), Bundling: &awscdklambdagoalpha.BundlingOptions{ GoBuildFlags: jsii.Strings(`-ldflags "-s -w"`), }, Environment: &map[string]*string{ "BUCKET_NAME": bucket.BucketName(), "TABLE_NAME": table.TableName(), }, })- 使用 alpha 模块
awscdklambdagoalpha/v2的NewGoFunction:CDK 在合成阶段自动对./lambda-handler目录下的 Go 代码执行编译与打包(bundling),无需手动预编译二进制; - 运行时为
PROVIDED_AL2023(Go 自定义运行时基于 Amazon Linux 2023); -ldflags "-s -w"用于剥离符号表与调试信息,减小产物体积;- 通过环境变量把
BUCKET_NAME与TABLE_NAME注入 Lambda,处理器运行时无需硬编码资源名。
4. 授权 Rekognition 识别权限
statement := awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{ Actions: &[]*string{jsii.String("rekognition:DetectLabels")}, Resources: &[]*string{jsii.String("*")}, }) function.AddToRolePolicy(statement)- 为 Lambda 执行角色追加一条内联策略,仅授予
rekognition:DetectLabels一个动作; - 注意
Resources: "*":Rekognition 的DetectLabels接口不需要指定具体的资源 ARN,属于 API 级权限,此处通配符是必要的。
5. S3 事件通知:按文件后缀过滤触发
//Add event notifications for bucket bucket.AddEventNotification(awss3.EventType_OBJECT_CREATED, awss3notifications.NewLambdaDestination(function), &awss3.NotificationKeyFilter{ Suffix: jsii.String(".jpg"), }) bucket.AddEventNotification(awss3.EventType_OBJECT_CREATED, awss3notifications.NewLambdaDestination(function), &awss3.NotificationKeyFilter{ Suffix: jsii.String(".jpeg"), }) bucket.AddEventNotification(awss3.EventType_OBJECT_CREATED, awss3notifications.NewLambdaDestination(function), &awss3.NotificationKeyFilter{ Suffix: jsii.String(".png"), })- 监听
OBJECT_CREATED(对象创建)事件,将 Lambda 作为事件目标(destination),CDK 会自动生成对应的 Lambda 资源策略(resource policy)允许 S3 调用; - 通过
NotificationKeyFilter.Suffix限定只处理.jpg、.jpeg、.png三种图片格式,避免其他类型对象(如文本、视频)触发无意义的识别调用。
6. 授予读写权限
table.GrantReadWriteData(function) bucket.GrantReadWrite(function, nil)table.GrantReadWriteData自动为 Lambda 执行角色附加 DynamoDB 表的读写策略;bucket.GrantReadWrite附加 S3 桶的读写策略,让 Lambda 能从桶中读取图片对象(供 Rekognition 拉取)。
7. CloudFormation 输出(Outputs)
栈末尾定义了 4 个输出(见 rekognition-lambda-s3-trigger.go#L82-L96):
| 输出逻辑名 | 含义 |
|---|---|
UploadImageToS3 | 直接给出可复制的上传命令:aws s3 cp <local-path-to-image> s3://<bucket>/,用于触发识别流程 |
DynamoDBTable | DynamoDB 表名,识别结果存储位置 |
LambdaFunction | Lambda 函数名 |
LambdaFunctionLogs | Lambda 对应的 CloudWatch 日志组名,方便排查运行日志 |
Lambda 处理器源码解析
处理器位于 lambda-handler/main.go,通过lambda.Start(handler)注册入口,使用 AWS SDK for Go v2(aws-sdk-go-v2)访问 Rekognition 与 DynamoDB。
事件结构解析
type Event struct { Records []struct { S3 struct { Object struct { Key string `json:"key"` } `json:"object"` } `json:"s3"` } `json:"Records"` }只解析所需字段:Records[0].S3.Object.Key即被上传对象的 key(图片名),并以此为图片名与识别结果的关联键。
调用 Rekognition DetectLabels
detectLabelsInput := &rekognition.DetectLabelsInput{ Image: &rekognitionTypes.Image{ S3Object: &rekognitionTypes.S3Object{ Bucket: aws.String(os.Getenv("BUCKET_NAME")), Name: aws.String(key), }, }, MaxLabels: aws.Int32(10), MinConfidence: aws.Float32(70), } detectLabelsOutput, err := rekognitionClient.DetectLabels(context.TODO(), detectLabelsInput)- 图片源直接指向 S3 对象,Rekognition 服务端从桶中拉取图片,Lambda 无需下载图片再上传(当然,读取桶对象仍需 S3 读权限,即前面
bucket.GrantReadWrite的作用); MaxLabels = 10:最多返回 10 个标签;MinConfidence = 70:只保留置信度 ≥ 70% 的标签,过滤掉低置信度的噪声结果;- 识别出的标签名收集进
labels切片并通过fmt.Println输出到 CloudWatch 日志。
写入 DynamoDB(防重复)
putItemInput := &dynamodb.PutItemInput{ TableName: aws.String(tableName), Item: map[string]types.AttributeValue{ "image_name": &types.AttributeValueMemberS{Value: key}, "labels": &types.AttributeValueMemberS{Value: fmt.Sprintf("%v", labels)}, }, ConditionExpression: aws.String("attribute_not_exists(image_name)"), }- 主键
image_name存入图片 key,属性labels存入标签列表(以 Go 切片格式化字符串存储); - 通过
ConditionExpression: attribute_not_exists(image_name)保证同一图片只写入一次,重复上传同名对象不会产生多条记录——这是一个容易被忽略的幂等细节。
部署与验证
依赖与运行环境
先确认满足前置条件:已配置 AWS 凭证(aws configure或环境变量),且本机已安装 AWS CDK CLI 与 Go 1.25+(go.mod 声明go 1.25.0)。
管理 Go 依赖
按 README 的说明,运行:
go mod tidy该命令根据go.mod/go.sum整理依赖。本项目依赖包括 CDK Go 模块awscdk/v2 v2.262.0、alpha 模块awscdklambdagoalpha/v2,以及aws-lambda-go、aws-sdk-go-v2(dynamodb、rekognition)等,详见 go.mod。
合成 CloudFormation 模板
cdk synthcdk.json 中的app字段定义为:
{ "app": "go mod download && go run rekognition-lambda-s3-trigger.go" }即每次合成时先自动下载 Go 依赖再运行栈程序,把生成的 CloudFormation 模板输出到cdk.out目录。cdk synth不产生任何真实云资源,适合在部署前审查生成的模板。
部署
cdk deploycdk deploy将栈部署(或重新部署)到你的 AWS 账户。部署完成后,根据控制台输出的UploadImageToS3提示,上传一张图片触发流程:
aws s3 cp <local-path-to-image> s3://<bucket>/随后可到 DynamoDB 控制台查看以image_name为分区键的记录,或在 CloudWatch 日志组中查看 Lambda 打印的标签列表。
单元断言测试
仓库附带 rekognition-lambda-s3-trigger_test.go,属于 CDK 模板断言测试(无需真实部署即可运行):通过assertions.Template_FromStack合成栈模板,断言资源数量与属性,例如:
AWS::S3::Bucket资源数量为 1;AWS::DynamoDB::Table的AttributeDefinitions包含image_name(类型S)。
可运行go test ./...或cdk test验证基础设施代码的正确性,防止后续改动破坏资源配置。
扩展与注意事项
- 支持更多图片格式:若需处理
.gif、.webp等格式,参照 rekognition-lambda-s3-trigger.go#L69-L77 追加AddEventNotification与对应的NotificationKeyFilter.Suffix即可; - 调整识别精度:
MaxLabels与MinConfidence两个参数可根据业务在 lambda-handler/main.go#L41-L50 中调整,例如电商图片可提高置信度阈值; - 生产化改造:示例中使用
RemovalPolicy_DESTROY、env()返回nil等开发友好的默认值,生产部署应显式指定环境(account/region),并为桶、表设置合适的删除保护与备份策略; - 结果存储结构:
labels以字符串形式存储 Go 切片格式化结果,若需要结构化查询(如按标签检索),可考虑将标签拆分为 List 类型属性或单独建立二级索引。
本文所涉及的完整代码、测试与配置均可直接参考 go/rekognition-lambda-s3-trigger 目录下的源码进行二次开发。
【免费下载链接】aws-cdk-examples
Example projects using the AWS CDK
相关推荐
AWS CDK Go 实战:构建 Lambda 函数写入 DynamoDB 的无服务器示例
AWS CDK Go 实战:构建 Lambda 函数写入 DynamoDB 的无服务器示例 本指南基于 aws cdk examples 仓库中的 Go 语言示
aws-cdk-examples Go 实战:从容器镜像部署 Lambda 并触发 S3 事件通知
aws cdk examples Go 实战:从容器镜像部署 Lambda 并触发 S3 事件通知 本指南以 aws cdk examples 仓库中 go/l
30分钟上手:用AWS SDK for Go + Rekognition构建企业级图像识别系统
30分钟上手:用AWS SDK for Go + Rekognition构建企业级图像识别系统 AWS SDK for Go是Go编程语言的AWS开发工具包,它
后端云原生开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考