Хранилище BLOB-объектов Azure | AcquireLeaseAsync, синхронно дождитесь снятия блокировки
Сейчас я делаю 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 ответ
Ошибка (вероятно, код =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;
}
}
}
Использование вышеуказанного метода в функции лазурь:
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 для получения дополнительных шаблонов и т. Д. В распределенной архитектуре без событий, управляемой событиями.