Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
438 views
in Technique[技术] by (71.8m points)

c# - Azure Blob Storage | AcquireLeaseAsync, synchronously wait until lock is released

Right now I'm making a HTTP serverless function with Azure Functions and with that I need to make my incoming requests synchronous when accessing a single Blob Storage Item on my Storage Account.

What I want to happen is the following:

// 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...

However I noticed when I try to get Blob on Request 2, it doesn't synchronously wait until the Blob lease is released from Request 1, it simply just returns an error which says that there's already an active Lease on this blob, and then just continues.

Is it possible to have the above synchronous system in an Azure Function?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The error (probably a code=409) what you are received is correct when you acquired a lease blob. This is a perfect behavior for serverless distributed model, where more functions (jobs, workers, etc.) want to have an exclusive access on the lease blob.

Only one of them can be a winner and the others must periodically asking again for their acquire lease. It is recommended during this acquiring period use a random waiting time.

The following code snippet shows an example of this "loop logic" in the azure function:

    // 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;
          }
      }
   }

the usage of the above method in the azure function:

    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));
       }
    }

Also, have a look at my article Using Azure Lease Blob for more patterns, etc. in the serverless event driven distributed architecture.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...