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

Amplify项目TS/Node环境下如何动态创建AWS Cron定时任务

Amplify 动态Cron任务体系实现方案

核心实现基于AWS EventBridge Scheduler服务,完全通过代码完成定时任务的创建、调度、销毁,无需手动操作CLI或Web控制台,适配TypeScript/Node技术栈。整套体系分为两层:

  • 主任务层:你已通过Amplify CLI创建的固定调度Lambda,作为任务调度入口
  • 次级任务层:主任务执行过程中动态生成的调度规则,可触发任意Lambda或其他AWS服务,支持一次性延迟执行、固定速率执行、Cron周期执行,任务完成后可自动清理规则或继续调度新任务

前置配置

1. 给主任务Lambda加权限

在Amplify项目对应主Lambda的目录下找到custom-policies.json(没有就新建),添加以下权限配置,执行amplify push后权限会自动部署,无需手动操作IAM控制台:

[
  {
    "Action": [
      "scheduler:CreateSchedule",
      "scheduler:DeleteSchedule",
      "scheduler:UpdateSchedule",
      "scheduler:GetSchedule"
    ],
    "Resource": ["arn:aws:scheduler:*:*:schedule/*/dynamic-tasks/*"]
  },
  {
    "Action": ["lambda:GetFunction"],
    "Resource": ["arn:aws:lambda:*:*:function:*"]
  }
]

2. 创建调度服务角色

首次使用时创建一个EventBridge Scheduler专用的执行角色:

  • 信任策略配置为允许scheduler.amazonaws.com服务代入角色
  • 角色权限添加lambda:InvokeFunction权限,允许调度服务调用你的Lambda函数
  • 将该角色的ARN配置到Amplify的环境变量SCHEDULER_ROLE_ARN中,所有动态调度复用此角色即可

3. 安装依赖

在主Lambda项目下安装AWS SDK对应客户端:
npm install @aws-sdk/client-scheduler @aws-sdk/client-lambda

Amplify Node运行时已内置AWS SDK v3,安装指定版本可避免版本兼容问题


核心代码实现(TypeScript)

初始化客户端

import { 
  SchedulerClient, 
  CreateScheduleCommand, 
  DeleteScheduleCommand, 
  FlexibleTimeWindowMode 
} from "@aws-sdk/client-scheduler";
import { LambdaClient, GetFunctionCommand } from "@aws-sdk/client-lambda";

// 客户端默认使用Lambda执行角色的权限,无需硬编码密钥
const schedulerClient = new SchedulerClient({ region: process.env.AWS_REGION });
const lambdaClient = new LambdaClient({ region: process.env.AWS_REGION });

// 按Amplify环境区分调度组,避免测试/生产资源混淆
const SCHEDULE_GROUP_NAME = `${process.env.ENV}-dynamic-tasks`;

通用调度方法封装

/**
 * 动态创建触发Lambda的定时任务
 * @param scheduleName 任务唯一标识,建议拼接业务ID/时间戳避免重名
 * @param targetLambdaName 要触发的次级Lambda函数名
 * @param scheduleExpression 调度表达式,支持at(一次性)、rate(固定速率)、cron(周期)三种格式
 * @param input 传给次级Lambda的事件参数
 * @param deleteAfterRun 执行完成后是否自动删除调度规则,一次性任务设为true
 */
async function createDynamicLambdaSchedule(
  scheduleName: string,
  targetLambdaName: string,
  scheduleExpression: string,
  input: Record<string, any>,
  deleteAfterRun: boolean = false
) {
  // 自动获取目标Lambda的ARN
  const lambdaInfo = await lambdaClient.send(new GetFunctionCommand({
    FunctionName: targetLambdaName
  }));
  const lambdaArn = lambdaInfo.Configuration?.FunctionArn;
  if (!lambdaArn) throw new Error(`目标Lambda不存在: ${targetLambdaName}`);

  const createRes = await schedulerClient.send(new CreateScheduleCommand({
    Name: scheduleName,
    GroupName: SCHEDULE_GROUP_NAME,
    ScheduleExpression: scheduleExpression,
    // 关闭弹性时间窗口,到点立即触发
    FlexibleTimeWindow: { Mode: FlexibleTimeWindowMode.OFF },
    Target: {
      Arn: lambdaArn,
      RoleArn: process.env.SCHEDULER_ROLE_ARN,
      Input: JSON.stringify(input)
    },
    // 配置任务执行完成后的动作
    ActionAfterCompletion: deleteAfterRun ? 'DELETE' : 'NONE'
  }));

  return createRes;
}

/**
 * 删除不需要的定时任务
 * @param scheduleName 任务唯一标识
 */
async function deleteDynamicSchedule(scheduleName: string) {
  return schedulerClient.send(new DeleteScheduleCommand({
    Name: scheduleName,
    GroupName: SCHEDULE_GROUP_NAME
  }));
}

主任务中调用示例

export const handler = async (event: any) => {
  // 原有主任务业务逻辑
  console.log('主任务开始执行', event);
  // ...... 你的业务代码 ......
  console.log('主任务执行完成,开始调度次级任务');

  // 示例1:创建2小时后执行的一次性数据清理任务
  const oneTimeRunTime = new Date(Date.now() + 2 * 60 * 60 * 1000);
  // 一次性任务使用at表达式,参数为ISO8601格式时间
  const oneTimeExpression = `at(${oneTimeRunTime.toISOString()})`;
  await createDynamicLambdaSchedule(
    `cleanup-${Date.now()}`,
    process.env.CLEANUP_LAMBDA_NAME!, // 次级Lambda名配置在环境变量中
    oneTimeExpression,
    { bizId: 'order-12345', type: 'temp-cleanup' },
    true // 执行完自动删除规则
  );

  // 示例2:创建每天北京时间凌晨1点执行的日报任务
  // 注意:EventBridge默认使用UTC时间,北京时间UTC+8,对应UTC时间17点
  const dailyCronExpression = 'cron(0 17 * * ? *)';
  await createDynamicLambdaSchedule(
    `daily-report-task`,
    process.env.REPORT_LAMBDA_NAME!,
    dailyCronExpression,
    { reportType: 'daily' },
    false // 周期任务不自动删除,不需要时调用delete方法移除
  );

  return { code: 0, msg: '主任务执行完成,次级任务调度成功' };
};

注意事项

  • 时区问题:EventBridge所有时间表达式默认使用UTC时区,配置Cron/一次性任务时必须做时区偏移,避免触发时间不符合预期
  • 命名规范:调度任务名称全局唯一,建议拼接业务ID、时间戳,重名会导致创建失败
  • 资源清理:一次性任务务必开启ActionAfterCompletion: 'DELETE',避免无用规则堆积产生额外费用
  • 环境隔离:所有资源名称、配置项通过Amplify环境变量注入,不要硬编码,避免测试环境操作生产资源
  • 触发限制:EventBridge Scheduler最小调度精度为1分钟,不支持秒级触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:45:42