You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Serverless Framework部署绑定DLQ的SQS时,首次部署RedrivePolicy失败

Serverless Framework首次部署关联DLQ的SQS队列失败

问题现象

首次完整部署包含死信队列(DLQ)的SQS队列及关联Lambda时,出现CREATE_FAILED错误,CloudFormation返回如下报错:

Resource handler returned message: "Invalid request provided: Error occurred while ReceiveMessage. SQS Error Code: AWS.SimpleQueueService.NonExistentQueue. SQS Error Message: The specified queue does not exist for this wsdl version.(Service: Lambda, Status Code: 400)(HandlerErrorCode: InvalidRequest)"

但如果先部署好DLQ和SQS队列,再单独添加RedrivePolicy配置,部署就能正常完成。

相关配置代码

serverless.ts

import type { AWS } from '@serverless/typescript';

// Lambdas
import getMessage from './src/functions/add-to-pros';

const serverlessConfiguration: AWS = {
  service: 'dlq-service',
  frameworkVersion: '3',
  custom: {
    stageType: '${opt:stage, env:AWS_STAGE, "dev"}',
    envType: '${env:ENV_TYPE, "dev"}',
    apiDomainName: 'api.${self:custom.hostedZoneName}',
    apiBasePath: 'api-${self:custom.stageType}-${self:service}',

    // SQS Queues
    getMessageQueue: 'GetMessageQueue',
    getMessageQueueName: '${self:service}-add-to-pros-queue-${self:provider.stage}',
    getMessageQueueArn: {
      'Fn::Join': [':', ['arn', 'aws', 'sqs', { Ref: 'AWS::Region' }, { Ref: 'AWS::AccountId' }, '${self:custom.getMessageQueueName}']],
    },
    getMessageQueueDLQ: 'GetMessageQueueDLQ',
    getMessageQueueDLQName: '${self:service}-add-to-pros-queue-dlq-${self:provider.stage}',

    esbuild: {
      bundle: true,
      minify: false,
      sourcemap: true,
      exclude: ['aws-sdk'],
      target: 'node16',
      define: { 'require.resolve': undefined },
      platform: 'node',
      concurrency: 10,
      loader: { '.html': 'text' },
    },
  },
  plugins: ['serverless-esbuild', 'serverless-deployment-bucket', 'serverless-offline'],
  provider: {
    name: 'aws',
    runtime: 'nodejs16.x',
    stage: '${self:custom.stageType}',
    region: 'eu-west-3',
    deploymentBucket: {
      name: '${self:service}-${self:custom.envType}-${self:provider.region}-deployment-bucket-2',
    },
  },
  functions: {
    getMessage,
  },
  package: {
    // When true optimise lambda performance but increase deployment time
    individually: !!process.env.STAGE_TYPE && process.env.STAGE_TYPE !== 'dev',
  },
  resources: {
    Resources: {
      // Dead Letter Queues
      GetMessageQueueDLQ: {
        Type: 'AWS::SQS::Queue',
        Properties: {
          QueueName: '${self:custom.getMessageQueueDLQName}',
          MessageRetentionPeriod: 1209600, // 14 days in seconds
        },
      },

      // Queues
      GetMessageQueue: {
        DependsOn: ['${self:custom.getMessageQueueDLQ}'],
        Type: 'AWS::SQS::Queue',
        Properties: {
          QueueName: '${self:custom.getMessageQueueName}',
          RedrivePolicy: {
            deadLetterTargetArn: {
              'Fn::GetAtt': ['${self:custom.getMessageQueueDLQ}', 'Arn'],
            },
            maxReceiveCount: 3,
          },
          VisibilityTimeout: 900,
        },
      },
    },
  },
};

module.exports = serverlessConfiguration;

getMessage lambda src/functions/handler.ts

export async function main(event: SQSEvent): Promise<void> {
  try {
    logger.info(event);
  } catch (error) {
    logger.error(error);
  }
}

getMessage lambda src/functions/index.ts

import { getCurrentFolderPath } from '@libs/utils/handler-resolver';

export default {
  handler: `${getCurrentFolderPath(__dirname)}/handler.main`,
  memorySize: 256,
  events: [
    {
      sqs: {
        arn: '${self:custom.getMessageQueueArn}',
      },
    },
  ],
};

问题原因

Lambda事件中引用的SQS队列ARN是通过Fn::Join手动拼接的,这种方式无法让CloudFormation自动建立Lambda与SQS队列的依赖关系。部署时,CloudFormation可能优先创建Lambda资源,此时SQS队列尚未完成创建,导致Lambda尝试关联不存在的队列,触发报错。

而后续单独添加RedrivePolicy时,队列已经存在,所以不会出现问题。

解决方案

方案1:修改SQS ARN的引用方式

在serverless.ts的custom配置中,将手动拼接的getMessageQueueArn改为通过Fn::GetAtt引用队列资源的ARN,确保CloudFormation识别依赖关系:

// 替换原来的getMessageQueueArn
getMessageQueueArn: {
  'Fn::GetAtt': ['GetMessageQueue', 'Arn'],
},

方案2:直接在Lambda事件中引用队列资源

在Lambda的事件配置中,直接通过Fn::GetAtt获取队列ARN,跳过自定义的ARN变量:

// 修改src/functions/index.ts中的events配置
events: [
  {
    sqs: {
      arn: {
        'Fn::GetAtt': ['GetMessageQueue', 'Arn'],
      },
    },
  },
],

方案3:显式添加Lambda对SQS队列的依赖

如果需要保留原有的ARN拼接方式,可以在Lambda资源中显式添加DependsOn,确保Lambda在队列创建完成后再部署:
在serverless.ts的resources.Resources中添加Lambda的资源定义(如果尚未定义),并指定依赖:

resources: {
  Resources: {
    // ... 原有DLQ和队列定义
    GetMessageFunction: {
      Type: 'AWS::Lambda::Function',
      DependsOn: ['GetMessageQueue'],
      // 其他Lambda配置(Serverless自动生成的资源逻辑ID通常为{函数名}Function)
    },
  },
},

验证修改

修改完成后,重新执行serverless deploy,此时CloudFormation会按顺序创建DLQ、主SQS队列,最后创建关联的Lambda,避免队列不存在的错误。

内容的提问来源于stack exchange,提问作者TheSmartMonkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 08:10:08