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
相关产品推荐
相关产品推荐

