Azure Blob Trigger通过SFTP上传时触发两次问题求助
Azure Blob Trigger SFTP上传重复触发问题解决方案
问题原因
SFTP客户端上传文件时,通常会分阶段操作:比如先创建空的目标文件再逐步写入内容,或是先上传临时文件、完成后重命名为目标文件名。这两种操作都会让Azure Blob存储生成两次BlobCreated事件,导致Trigger被触发两次。而手动上传时Azure门户的机制是一次性完成文件写入,只会触发一次事件。
解决方法
基于ETag校验过滤重复触发
在函数逻辑中先验证Blob是否处于稳定状态(上传完成),再执行业务逻辑。可以通过对比触发时的ETag和实时获取的Blob ETag来判断:public static async Task Run( [BlobTrigger("your-container/{name}", Connection = "AzureWebJobsStorage")] Stream myBlob, string name, string etag, ILogger log) { // 短暂延迟确保文件上传完成,时长根据实际场景调整 await Task.Delay(1500); var blobClient = new BlobServiceClient(Environment.GetEnvironmentVariable("AzureWebJobsStorage")) .GetBlobContainerClient("your-container") .GetBlobClient(name); var currentProps = await blobClient.GetPropertiesAsync(); // 如果ETag不一致,说明文件还在更新中,跳过处理 if (currentProps.ETag.ToString() != etag) { log.LogInformation($"File {name} is still uploading, skip this trigger."); return; } // 执行你的业务逻辑 log.LogInformation($"Processing file: {name}"); }配置Blob Trigger过滤规则
在host.json中开启忽略空Blob的设置,避免空文件触发事件,同时确认只监听BlobCreated事件:{ "version": "2.0", "extensions": { "blobs": { "trigger": { "ignoreEmptyBlobs": true, "blobCreatedEventTypes": ["Microsoft.Storage.BlobCreated"] } } } }调整SFTP客户端上传模式
检查你的SFTP客户端设置,关闭“原子上传”或“临时文件重命名”功能,改为直接覆盖目标文件。这样上传过程只会生成一次Blob事件,但需注意如果上传中断会导致文件损坏,需根据业务场景权衡。分布式锁避免多实例重复处理
如果函数部署了多实例,可利用Blob租约实现分布式锁,确保同一个文件只有一个实例处理:public static async Task Run( [BlobTrigger("your-container/{name}", Connection = "AzureWebJobsStorage")] Stream myBlob, string name, ILogger log) { var blobClient = new BlobServiceClient(Environment.GetEnvironmentVariable("AzureWebJobsStorage")) .GetBlobContainerClient("your-container") .GetBlobClient(name); // 尝试获取Blob租约,租期1分钟 try { using var lease = await blobClient.AcquireLeaseAsync(TimeSpan.FromMinutes(1)); // 执行业务逻辑 log.LogInformation($"Processing file {name} with lease: {lease.LeaseId}"); } catch (RequestFailedException ex) when (ex.Status == 409) { // 租约已被其他实例获取,跳过处理 log.LogInformation($"File {name} is being processed by another instance, skip."); } }
关于FixedDelayRetry无效的说明
[FixedDelayRetry(0, "00:00:10")]是用来控制函数执行失败后的重试行为,而你遇到的是两次独立的触发事件,并非单次触发后的重试,所以这个属性无法解决重复触发问题。
内容的提问来源于stack exchange,提问作者Furkan Moray
相关产品推荐
相关产品推荐

