如何通过AWS CDK2代码向SNS发布JSON消息?
使用AWS CDK2实现SNS JSON消息发布(API集成场景)
方案一:Lambda + SNS(灵活可控,支持消息预处理)
这种方案通过Lambda作为中间层接收API请求,处理JSON消息后发布到SNS,适合需要对消息做验证、转换等逻辑的场景。
CDK代码示例(TypeScript)
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as sns from 'aws-cdk-lib/aws-sns'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as apigateway from 'aws-cdk-lib/aws-apigateway'; export class SnsApiIntegrationStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // 创建SNS主题 const snsTopic = new sns.Topic(this, 'JsonMessageTopic', { displayName: 'JSON消息接收主题', }); // 创建处理消息发布的Lambda函数 const publishLambda = new lambda.Function(this, 'PublishSnsLambda', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', code: lambda.Code.fromInline(` const AWS = require('aws-sdk'); const sns = new AWS.SNS(); exports.handler = async (event) => { try { // 解析API请求的JSON Body const jsonMessage = JSON.parse(event.body); // 发布JSON消息到SNS await sns.publish({ TopicArn: process.env.SNS_TOPIC_ARN, Message: JSON.stringify(jsonMessage), MessageStructure: 'string' }).promise(); return { statusCode: 200, body: JSON.stringify({ success: true, msg: '消息已发布到SNS' }) }; } catch (err) { return { statusCode: 500, body: JSON.stringify({ success: false, err: err.message }) }; } }; `), environment: { SNS_TOPIC_ARN: snsTopic.topicArn, }, }); // 自动赋予Lambda发布SNS消息的权限 snsTopic.grantPublish(publishLambda); // 配置API Gateway,将POST请求转发到Lambda const api = new apigateway.RestApi(this, 'SnsPublishApi', { restApiName: 'SNS消息发布API', }); const publishResource = api.root.addResource('publish'); publishResource.addMethod('POST', new apigateway.LambdaIntegration(publishLambda, { proxy: true })); // 输出API访问地址和SNS主题ARN new cdk.CfnOutput(this, 'ApiEndpoint', { value: `${api.url}publish` }); new cdk.CfnOutput(this, 'SnsTopicArn', { value: snsTopic.topicArn }); } }
核心说明
- Lambda使用AWS SDK v2(Node.js 18+ runtime自带)调用SNS
publish接口,将JSON消息序列化为字符串发布 - 通过
grantPublish方法自动生成IAM权限,无需手动编写Policy - API Gateway采用Lambda代理集成,直接传递请求参数和响应
方案二:API Gateway直接集成SNS(轻量无服务器,无Lambda依赖)
如果不需要对消息做额外处理,可直接通过API Gateway的AWS集成调用SNS,省去Lambda层。
CDK代码示例(TypeScript)
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as sns from 'aws-cdk-lib/aws-sns'; import * as apigateway from 'aws-cdk-lib/aws-apigateway'; import * as iam from 'aws-cdk-lib/aws-iam'; export class DirectSnsApiIntegrationStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // 创建SNS主题 const snsTopic = new sns.Topic(this, 'DirectJsonTopic'); // 创建API Gateway const api = new apigateway.RestApi(this, 'DirectSnsPublishApi'); // 配置API Gateway到SNS的集成 const snsIntegration = new apigateway.AwsIntegration({ service: 'sns', action: 'Publish', options: { // 创建API Gateway调用SNS的IAM角色 credentialsRole: new iam.Role(this, 'ApiGatewaySnsRole', { assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSNSFullAccess') ] }), // 映射请求参数到SNS Publish接口 requestTemplates: { 'application/json': `{ "TopicArn": "${snsTopic.topicArn}", "Message": "$input.body" }` }, integrationResponses: [ { statusCode: '200', responseTemplates: { 'application/json': '{ "success": true, "msg": "消息发布成功" }' } } ] } }); // 添加API资源和POST方法 const publishResource = api.root.addResource('direct-publish'); publishResource.addMethod('POST', snsIntegration, { methodResponses: [{ statusCode: '200' }] }); // 输出API访问地址 new cdk.CfnOutput(this, 'DirectApiEndpoint', { value: `${api.url}direct-publish` }); } }
核心说明
- 直接利用API Gateway的AWS集成能力调用SNS的
Publish动作 - 需创建IAM角色赋予API Gateway调用SNS的权限
- 通过请求模板将API的JSON Body直接映射为SNS的
Message参数
部署验证
- 执行
cdk deploy部署栈 - 调用输出的API地址,发送POST请求,Body为JSON格式数据
- 查看SNS主题的订阅者(如邮箱、Lambda)是否收到消息
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

