使用serverless.yml创建Kinesis触发Lambda遇竞态条件问题
解决Serverless部署Kinesis触发Lambda的竞态条件问题
这个坑我之前踩过!确实是CloudFormation并行部署搞的鬼——当你在同一个serverless.yml里同时定义Kinesis流和Lambda触发器时,CloudFormation会尝试并行创建这两个资源,但Lambda的事件源映射会在Kinesis流还没完全就绪(比如还没完成全局同步)的时候就去关联,直接触发报错。
下面给你两种靠谱的解决方法,都是通过强制资源创建顺序来避免竞态:
方法1:手动定义事件源映射并添加DependsOn
Serverless会自动为Kinesis触发器生成一个CloudFormation事件源映射资源,我们可以手动覆盖这个资源,明确让它依赖于Kinesis流的创建完成:
service: kinesis-lambda-service frameworkVersion: '3' provider: name: aws runtime: nodejs18.x functions: kinesisHandler: handler: handler.processKinesisRecords # 保留基础事件配置,实际映射在resources中手动定义 events: - stream: type: kinesis arn: !GetAtt MyKinesisStream.Arn batchSize: 100 startingPosition: TRIM_HORIZON resources: Resources: # 自定义Kinesis流 MyKinesisStream: Type: AWS::Kinesis::Stream Properties: ShardCount: 1 Name: MyAppKinesisStream # 覆盖自动生成的事件源映射,添加依赖确保流先创建完成 kinesisHandlerKinesisEventSourceMapping: Type: AWS::Lambda::EventSourceMapping DependsOn: MyKinesisStream Properties: EventSourceArn: !GetAtt MyKinesisStream.Arn FunctionName: !GetAtt kinesisHandlerLambdaFunction.Arn BatchSize: 100 StartingPosition: TRIM_HORIZON
方法2:使用函数级dependsOn(简化版)
如果你不想手动写事件源映射,也可以直接让Lambda函数本身依赖于Kinesis流,这样CloudFormation会先完成流的创建,再部署函数和触发器:
service: kinesis-lambda-service frameworkVersion: '3' provider: name: aws runtime: nodejs18.x functions: kinesisHandler: handler: handler.processKinesisRecords dependsOn: MyKinesisStream # 强制函数依赖Kinesis流的创建 events: - stream: type: kinesis arn: !GetAtt MyKinesisStream.Arn batchSize: 100 startingPosition: TRIM_HORIZON resources: Resources: MyKinesisStream: Type: AWS::Kinesis::Stream Properties: ShardCount: 1 Name: MyAppKinesisStream
原理说明
CloudFormation默认会并行创建所有没有显式依赖的资源,添加DependsOn后,它会严格按照依赖顺序执行:先创建Kinesis流,等流的状态彻底变为ACTIVE后,再创建Lambda函数(或事件源映射),从根源上避免了竞态条件。
我自己用第一种方法解决过完全一样的问题,精准控制触发器的创建时机,成功率很高。
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

