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

Azure Timer Trigger函数并发问题:如何确保单实例串行执行

Azure Timer Trigger 串行执行解决方案

方法一:单实例部署+函数级并发控制

  • 在Azure门户的函数应用配置中,找到缩放选项,将缩放模式改为手动,实例数设为1,确保整个函数应用仅运行一个实例。
  • 修改host.json,添加Timer Trigger的并发限制配置,强制单个函数同一时间只执行一次:
{
  "version": "2.0",
  "extensions": {
    "timer": {
      "maxConcurrentCalls": 1
    }
  }
}

这样即使定时器触发了新任务,也会排队等待前一个实例执行完毕后再启动。

方法二:分布式锁(适配多实例场景)

如果未来需要多实例部署,不想限制单实例,可借助Azure存储的Blob Lease实现分布式锁:

  • 每次函数启动时,尝试获取指定Blob的租约(有效期设为比函数最长执行时间稍长)。获取成功则执行任务,失败则直接退出本次触发。
  • C#示例代码:
public static async Task Run([TimerTrigger("0 * * * * *")] TimerInfo myTimer, ILogger log, ExecutionContext context)
{
    var storageConn = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
    var blobClient = new BlobClient(storageConn, "lock-container", "task-lock.tmp");
    
    await blobClient.CreateIfNotExistsAsync();
    
    try
    {
        // 5分钟租约有效期,根据实际任务时长调整
        var lease = await blobClient.AcquireLeaseAsync(TimeSpan.FromMinutes(5));
        
        try
        {
            log.LogInformation("开始执行任务");
            // 替换为你的业务逻辑,这里模拟1.5分钟的任务
            await Task.Delay(TimeSpan.FromMinutes(1.5));
            log.LogInformation("任务执行完成");
        }
        finally
        {
            // 执行完释放租约
            await blobClient.ReleaseLeaseAsync(lease.Value);
        }
    }
    catch (RequestFailedException ex) when (ex.Status == 409)
    {
        // 409表示租约已被占用,跳过本次触发
        log.LogInformation("已有实例在运行,本次触发跳过");
    }
}
  • 注意:确保函数应用已配置AzureWebJobsStorage环境变量,提前创建好名为lock-container的存储容器。

方法三:内置延迟与跳过配置

修改host.json的Timer Trigger监控配置,让定时器跳过未执行的触发:

{
  "version": "2.0",
  "extensions": {
    "timer": {
      "scheduleMonitor": {
        "skipMissedRuns": true
      }
    }
  }
}

skipMissedRuns设为true后,如果前一次任务未完成,定时器会直接跳过当前触发,直到下一个周期。该方法适合简单场景,可靠性略低于锁机制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 22:45:39