Хранилище BLOB-объектов Azure |AcquireLeaseAsync, синхронно дождитесь снятия блокировки - PullRequest
0 голосов
/ 24 сентября 2018

Сейчас я делаю HTTP-функцию без сервера с помощью функций Azure, и с этим мне нужно синхронизировать свои входящие запросы при доступе к одному элементу хранилища 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...

Однако, как я заметил, когда я пытаюсь получить Blob по запросу 2, он не синхронно ожидает освобождения аренды Blob из запроса 1, он просто возвращает ошибку, которая говоритчто этот BLOB-объект уже имеет активную аренду, а затем просто продолжает.

Возможно ли использовать вышеуказанную синхронную систему в функции Azure?

1 Ответ

0 голосов
/ 24 сентября 2018

Ошибка (вероятно, код = 409) того, что вы получите, является правильной, когда вы приобрели объект аренды.Это идеальное поведение для безсерверной распределенной модели, где больше функций (рабочих мест, рабочих и т. Д.) Хотят иметь эксклюзивный доступ к объекту аренды.

Только один из них может быть победителем, а другие должны периодически запрашивать аренду.В этот период сбора рекомендуется использовать случайное время ожидания.

В следующем фрагменте кода показан пример этой "логики цикла" в функции 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));
       }
    }

Также ознакомьтесь с моей статьей Использование Azure Lease Blob для получения дополнительных шаблонов и т. Д. В распределенной архитектуре, управляемой событиями без сервера.

...