Azure Blob存储| AcquireLeaseAsync,同步等待直到锁释放

时间:2018-09-24 14:42:27

标签: c# .net azure azure-functions azure-storage-blobs

现在,我正在使用Azure Functions来实现HTTP无服务器功能,并且在访问存储帐户上的单个Blob存储项时,我需要使传入的请求同步。

我想发生的事情如下:

// Incoming Request 1

// .. Get blob

await myBlob.AcquireLeaseAsync(TimeSpan.FromMinutes(1), leaseId);

// .. 10 seconds later

await myblob.ReleaseLeaseAsync(AccessCondition.GenerateEmptyCondition());


//
// MEANWHILE
//

// Incoming Request 2 (Happens 1-2 seconds after Request 1)

// .. Get blob    
// .. -- Wait until Lease is released from Request 1 --


await myBlob.AcquireLeaseAsync(TimeSpan.FromMinutes(1), leaseId);

// Repeat...

但是我注意到,当我尝试在请求2上获取Blob时,它不会同步等待直到从请求1释放Blob租约,它只是返回一个错误,表明该Blob上已有有效的Lease,然后继续。

Azure功能中是否可以具有上述同步系统?

1 个答案:

答案 0 :(得分:5)

获取租约Blob时收到的错误(可能是代码= 409)是正确的。对于无服务器的分布式模型,这是一种完美的行为,在该模型中,更多功能(工作,工作者等)希望对租用Blob具有独占访问权。

其中只有一个可以成为赢家,其他人则必须定期再次要求其购置租约。 建议在此获取期间使用随机的等待时间。

以下代码段显示了azure函数中此“循环逻辑”的示例:

    // Acquireing a Lease blob
    public async static Task<string> LockingEntity(dynamic entity, int leaseTimeInSec = 60, string leaseId = null)
    {
       while (true)
       {
          try
          {
             string lid = await entity.AcquireLeaseAsync(TimeSpan.FromSeconds(leaseTimeInSec), leaseId);
             if (string.IsNullOrEmpty(lid))
                await Task.Delay(TimeSpan.FromMilliseconds(new Random(Guid.NewGuid().GetHashCode()).Next(250, 1000)));
             else
                return lid;
          }
          catch (StorageException ex)
          {
             if (ex.RequestInformation.HttpStatusCode != 409)
                throw;
          }
      }
   }

上述方法在azure函数中的用法:

    string leaseId = await LockingEntity(blockBlob);
    if (string.IsNullOrEmpty(leaseId) == false)
    {
       try
       {
          string esp = await blockBlob.DownloadTextAsync(Encoding.UTF8, AccessCondition.GenerateLeaseCondition(leaseId), null, null);
          state = JsonConvert.DeserializeObject<State>(esp);
          // …
       }
       finally
       {
          await blockBlob.ReleaseLeaseAsync(AccessCondition.GenerateLeaseCondition(leaseId));
       }
    }

另外,请参阅我的文章Using Azure Lease Blob,了解有关无服务器事件驱动的分布式体系结构中更多模式的信息。