【免费下载链接】aws-cdk-examples
Example projects using the AWS CDK
导读
本文基于 aws-cdk-examples 仓库中的 httpapi-eventbridge 示例,完整讲解如何用 AWS CDK(Go 语言)搭建一条「API Gateway HTTP API → Amazon EventBridge → CloudWatch Logs」的无服务器事件管道。读者将掌握 HTTP API 与 EventBridge 之间的 AWS 服务集成(service integration)配置方法、IAM 权限授予方式,以及部署、测试与验证的完整流程,可直接套用于日志上报、Webhook 事件接收、异步事件解耦等真实业务场景。
架构与工作原理
该示例的核心思路是:让 API Gateway HTTP API 通过内置的 AWS 服务集成(AWS service integration)直接把请求转发给 EventBridge,全程无需 Lambda 函数参与。
整个链路由以下组件构成,对应 http-api-eventbridge.go 中的实现:
- API Gateway HTTP API:对外暴露
POST /路由,作为客户端数据的统一入口; - EventBridge 自定义事件总线(Event Bus):接收 API Gateway 写入的事件;
- EventBridge 规则(Rule):匹配所有进入总线的事件;
- CloudWatch Logs 日志组:作为规则的投递目标,将全部事件落盘存储,便于检索与审计。
数据流向为:客户端curl发送 HTTP POST 请求 → API Gateway 根据集成配置将请求体映射为 EventBridgePutEvents调用 → 事件进入MyEventBus总线 → 规则myEventLoggerRule匹配该事件 → 事件被写入日志组/aws/events/MyEventBus。
源码级实现解析
1. 创建自定义事件总线
示例创建了一个名为MyEventBus的自定义事件总线,作为事件的汇聚点:
eventBus := awsevents.NewEventBus(stack, jsii.String("myEventBus"), &awsevents.EventBusProps{ EventBusName: jsii.String("MyEventBus"), })自定义总线相比默认总线(default)的优势在于:可以按业务域隔离事件,且规则的匹配与权限控制更加独立。
2. 创建匹配全部事件的规则
随后创建一条规则myEventLoggerRule,其事件模式(EventPattern)按当前部署区域进行过滤,效果上等价于捕获该总线上进入的所有事件:
eventLoggerRule := awsevents.NewRule(stack, jsii.String("myEventLoggerRule"), &awsevents.RuleProps{ Description: jsii.String("Log all events"), EventBus: eventBus, EventPattern: &awsevents.EventPattern{ Region: jsii.Strings(*props.Env.Region), }, })注意这里的props.Env.Region来自部署环境变量AWS_DEFAULT_REGION(见文末「部署前置条件」),因此事件模式会自动匹配当前部署区域,无需硬编码。
3. 以 CloudWatch Logs 作为规则投递目标
规则把事件发送到一个日志组/aws/events/MyEventBus:
logGroup := awslogs.NewLogGroup(stack, jsii.String("MyEventLogGroup"), &awslogs.LogGroupProps{ LogGroupName: jsii.String("/aws/events/MyEventBus"), }) eventLoggerRule.AddTarget(awseventstargets.NewCloudWatchLogGroup(logGroup, &awseventstargets.LogGroupProps{}))AddTarget是 CDK 提供的「规则→目标」绑定方法,底层会为 EventBridge 自动生成将事件写入 CloudWatch Logs 所需的 IAM 权限。
4. 创建 HTTP API 与 IAM 集成角色
示例创建一个名为myHttpApi的 HTTP API,并创建了一个由apigateway.amazonaws.com服务主体担任的 IAM 角色:
httpApi := awsapigatewayv2.NewHttpApi(stack, jsii.String("myHttpApi"), &awsapigatewayv2.HttpApiProps{ ApiName: jsii.String("myHttpApi"), }) apiRole := awsiam.NewRole(stack, jsii.String("myEventBridgeIntegrationRole"), &awsiam.RoleProps{ AssumedBy: awsiam.NewServicePrincipal(jsii.String("apigateway.amazonaws.com"), &awsiam.ServicePrincipalOpts{}), }) apiRole.AddToPolicy( awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{ Effect: awsiam.Effect_ALLOW, Resources: jsii.Strings(*eventBus.EventBusArn()), Actions: jsii.Strings("events:putEvents"), }), )该角色被授予对MyEventBus总线 ARN 执行events:putEvents的权限,这是 API Gateway 能够代表客户端向 EventBridge 写入事件的关键——缺失该权限时集成调用会返回 403。
5. 配置 EventBridge-PutEvents 服务集成
这是整个示例的精华所在。通过底层 L1 构造CfnIntegration,直接声明一个AWS_PROXY类型的服务集成:
eventbridgeIntegration := awsapigatewayv2.NewCfnIntegration(stack, jsii.String("myEventbridgeIntegration"), &awsapigatewayv2.CfnIntegrationProps{ ApiId: httpApi.HttpApiId(), IntegrationType: jsii.String("AWS_PROXY"), IntegrationSubtype: jsii.String("EventBridge-PutEvents"), CredentialsArn: apiRole.RoleArn(), RequestParameters: &map[string]string{ "Source": "WebApp", "DetailType": "MyDetailType", "Detail": "$request.body", "EventBusName": *eventBus.EventBusArn(), }, PayloadFormatVersion: jsii.String("1.0"), TimeoutInMillis: jsii.Number(10000.0), })各参数含义如下:
| 参数 | 值 | 说明 |
|---|---|---|
IntegrationType | AWS_PROXY | 服务集成类型,表示请求直接转发给 AWS 服务而非代理到 Lambda/HTTP 端点 |
IntegrationSubtype | EventBridge-PutEvents | 指定调用的 AWS 服务动作,即 EventBridge 的PutEventsAPI |
CredentialsArn | IAM 角色的 ARN | API Gateway 代入该角色执行集成调用 |
Source | WebApp | 写入事件的source字段,用于事件来源标识 |
DetailType | MyDetailType | 写入事件的detail-type字段 |
Detail | $request.body | 将 HTTP 请求体原样映射为事件的detail内容——这也是 README 测试时要求请求体包含Detail字段的原因 |
EventBusName | 事件总线 ARN | 事件写入的目标总线 |
PayloadFormatVersion | 1.0 | 集成负载格式版本 |
TimeoutInMillis | 10000 | 集成超时时间,10 秒 |
6. 绑定路由与输出端点地址
最后将POST /路由绑定到上述集成,并把 API 端点地址作为 CloudFormation 输出:
awsapigatewayv2.NewCfnRoute(stack, jsii.String("myEventRoute"), &awsapigatewayv2.CfnRouteProps{ ApiId: httpApi.HttpApiId(), RouteKey: jsii.String("POST /"), Target: jsii.String("integrations/" + *eventbridgeIntegration.Ref()), }) awscdk.NewCfnOutput(stack, jsii.String("apiUrl"), &awscdk.CfnOutputProps{ Value: httpApi.Url(), Description: jsii.String("HTTP API endpoint URL"), })Target的写法integrations/{integrationId}是 API Gateway v2 路由绑定集成的标准格式,Ref()返回集成资源的逻辑 ID。
部署前置条件与执行
前置条件
- 已安装 AWS CLI 并完成
aws configure认证配置; - 已安装 Node.js 与 AWS CDK CLI(仓库根目录 go/package.json 中锁定版本为
aws-cdk: 2.1133.0); - 已安装 Go(示例 go.mod 要求
go 1.25.0,并依赖github.com/aws/aws-cdk-go/awscdk/v2 v2.262.0); - 设置环境变量
AWS_DEFAULT_REGION(源码中的env()函数读取该变量决定部署区域)。
部署命令
在示例目录下执行:
cdk deploycdk.json中配置的启动命令为go mod download && go run http-api-eventbridge.go(见 cdk.json),因此 CDK 会自动下载 Go 依赖并运行应用完成部署/重新部署。部署结束后,终端会打印apiUrl输出,即 HTTP API 端点地址。
测试验证:发送事件并查看日志
第一步:发送测试请求
使用 README 提供的curl命令向 API 端点发送 POST 请求,将<YOUR_API_ENDPOINT>替换为部署输出中的地址:
curl --location --request POST '<YOUR_API_ENDPOINT>' --header 'Content-Type: application/json' \ --data-raw '{ "Detail":{ "message": "This is my test" } }'由于集成中Detail被映射为$request.body,请求体中的Detail对象会成为事件的detail内容。Content-Type: application/json头必不可少,API Gateway 需要据此正确解析请求体。
第二步:在 CloudWatch Logs 中验证
打开 AWS 管理控制台的 CloudWatch → Log groups,进入日志组/aws/events/MyEventBus,即可看到刚发送的事件记录。事件内容应包含source: "WebApp"、detail-type: "MyDetailType"以及请求体中的detail信息,证明整条链路已打通。
如果日志中没有出现记录,可按以下顺序排查:
- 确认使用了部署输出的正确端点地址;
- 确认 IAM 角色具备
events:putEvents权限(可检查 CloudWatch 日志中 API Gateway 的执行日志是否报 403); - 确认规则的事件模式与事件
region字段匹配(示例按部署区域过滤)。
测试用例:用 CDK 断言验证基础设施
仓库提供了配套的单元测试 http-api-eventbridge_test.go,通过Template_FromStack生成模板快照并断言关键资源,可作为 CI 中验证基础设施的正确方式:
template.HasResourceProperties(jsii.String("AWS::Events::EventBus"), map[string]interface{}{}) template.HasResourceProperties(jsii.String("AWS::Events::Rule"), map[string]interface{}{}) template.HasResource(jsii.String("AWS::ApiGatewayV2::Api"), map[string]interface{}{}) template.HasResourceProperties(jsii.String("AWS::IAM::Role"), map[string]interface{}{ "AssumeRolePolicyDocument": map[string]interface{}{ "Statement": []map[string]interface{}{ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": map[string]interface{}{ "Service": "apigateway.amazonaws.com", }, }, }, }, }) template.HasResourceProperties(jsii.String("AWS::ApiGatewayV2::Integration"), map[string]interface{}{ "IntegrationType": "AWS_PROXY", "IntegrationSubtype": "EventBridge-PutEvents", "RequestParameters": map[string]interface{}{ "Source": "WebApp", "DetailType": "MyDetailType", "Detail": "$request.body", }, })该测试验证了五个关键事实:事件总线、规则、HTTP API 均被创建;IAM 角色的信任策略仅允许apigateway.amazonaws.com代入;集成的类型为AWS_PROXY、子类型为EventBridge-PutEvents且请求参数映射正确。运行测试的方式:
go test ./...合成 CloudFormation 模板
如需查看 CDK 生成的 CloudFormation 模板,执行:
cdk synth输出文件位于当前目录的cdk.out目录下。通过查看合成后的模板,可以直观理解高层构造(NewEventBus、NewRule)最终展开成AWS::Events::EventBus、AWS::Events::Rule、AWS::ApiGatewayV2::Api、AWS::ApiGatewayV2::Integration、AWS::ApiGatewayV2::Route、AWS::IAM::Role、AWS::Logs::LogGroup等资源及其依赖关系,这也是排查权限缺失、资源引用错误等问题时的有力手段。
扩展与注意事项
- 无 Lambda 的纯服务集成:本模式利用 HTTP API 的
AWS_PROXY服务集成直连 EventBridge,省去了中间 Lambda 的冷启动时间与运行成本,是低延迟、低成本事件写入方案的典型参考。 - 事件内容定制:通过修改
RequestParameters中的Source、DetailType,可区分不同来源的事件;Detail也可改为静态值或$request.body之外的路径表达式。 - 超时与负载:集成超时被设置为 10 秒,事件负载大小受 EventBridge
PutEvents单条 256 KB 的上限约束,超大请求体需要在客户端先行拆分。 - 成本提示:该应用涉及 API Gateway、EventBridge、CloudWatch Logs 等服务,超出免费额度后会产生相应费用,请参考 AWS 定价页面,并注意部署完毕后及时
cdk destroy清理资源。
总而言之,go/httpapi-eventbridge 是一个结构清晰、可端到端验证的参考实现:部署一条命令、测试一条 curl、验证一处日志,非常适合作为「HTTP 入口 → 事件总线」架构的起点模板。
【免费下载链接】aws-cdk-examples
Example projects using the AWS CDK
相关推荐
使用 AWS CDK(Go)构建 EventBridge 到 SQS 的事件路由管道
使用 AWS CDK(Go)构建 EventBridge 到 SQS 的事件路由管道 导读 本篇文章基于 aws cdk examples 仓库中的 go/ev
使用 AWS CDK(C)构建 Lambda + API Gateway + S3 无服务器 Widget 服务:csharp/my-widget-service 实战指南
使用 AWS CDK(C )构建 Lambda + API Gateway + S3 无服务器 Widget 服务:csharp/my widget servi
使用 AWS CDK(Go)构建 Cognito 用户池与 API Gateway HTTP API JWT 鉴权
使用 AWS CDK(Go)构建 Cognito 用户池与 API Gateway HTTP API JWT 鉴权 导读 本指南基于 aws cdk examp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考