李甲蔚

你创想,云实现

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Blob Lease就是给Blob文件上锁,上锁以后直到lease过期的这段时间,只有拥有lease ID的有权限的访问者,才能删写该Blob文件。

Blob Lease包含以下五个操作:

  • Acquire,根据自定义lease ID(或者让系统自动生成),请求一个新的lease,并设置lease的过期时间(15s-60s或者是无限时间);
  • Renew,刷新现有的lease,lease过期时间从头计算;
  • Change,改变现有lease的ID;
  • Release,将lease立即释放,以便其他Client可以请求新的lease;
  • Break,将lease终止,在该操作发生以后,必须等lease过期时间过去以后,lease才真正被终止,或者可以自定义一个终止等待时长。

在Blob Lease的整个操作过程中,包含五种状态,如下图所示:

  • Available,可以获取新的lease;
  • Leased,Acquire操作成功,Blob被锁住;
  • Expired,lease过期,Blob锁释放;
  • Breaking,Break操作执行以后,当前lease还没到过期时间,Blob仍然被锁;
  • Broken,lease终止。

几点需要注意的地方:

  • 一旦lease过期,在Blob文件被修改或者再次上锁之前,Blob服务仍然保留着lease Id。Client还能够使用这个lease Id进行renew或者release操作。如果操作成功了,则说明在lease过期以后的这段时间里,Blob文件并没有被修改过。如果操作失败了,则说明Blob文件被修改过或者是拥有过了新的lease,这个时候就需要使用新的lease Id来给Blob上锁。
  • 一旦lease被释放(执行了Release操作),则该lease不能被Renew或者Break,强制执行将或者409 Conflict的异常信息。
  • Break操作时并不需要提供lease id,一般用来释放已存在的lease,并且不允许再次renew lease。这个操作一般是供管理员使用,用来重置lease状态。
  • 对于Acquire方法,早期版本的Blob不提供自定义Lease Id,在这里我们来探讨一下自定义Lease Id的好处。如果acquire操作在服务端成功了,但是在返回客户端响应时失败了,那这时client可以使用相同的lease id进行重试,而不需要先让之前的lease失效(终止)再acquire一个新的Lease;
  • 在执行Acquire操作时,如果过期时间设置为-1,则该lease永不过期。当需要自己控制lease的生命周期时,可以如此设置。如果需要设置过期时间,时间范围只能是15s至60s。

好了,了解完一些概念性的内容,我们来通过代码验证一下这些概念。

整个例子是一个简单的web应用程序,访问位于云端的Blob服务,角色为所有者(owner of storage account),当然,也可以通过有权限的匿名用户来操作。

(关于Blob权限设置请参看 Windows Azure: Blob Container的访问权限与策略设置

页面结构很简单,包含两部分,如图所示:

蓝框内是列出容器内所有的Block Blob文件,红框内是对选定的Blob文件进行lease各种操作。

列出容器内所有Block Blob文件代码:

   1: CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
   2:             CloudBlobClient blobClient = new CloudBlobClient(storageAccount.BlobEndpoint);
   3:             CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainerforlease");
   4:             blobContainer.CreateIfNotExists();
   5:  
   6:             IEnumerable<IListBlobItem> blobItems = blobContainer.ListBlobs(null, true, BlobListingDetails.None, null, null);
   7:             List<CloudBlockBlob> blockBlobs = new List<CloudBlockBlob>();
   8:             foreach (IListBlobItem item in blobItems)
   9:             {
  10:                 if (item.GetType() == typeof(CloudBlockBlob))
  11:                 {
  12:                     blockBlobs.Add((CloudBlockBlob)item);
  13:                 }
  14:             }
  15:             BlobItemGridView.DataSource = blockBlobs;
  16:             BlobItemGridView.DataBind();

 

上传文件代码:

   1: try
   2:             {
   3:                 CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
   4:                 CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
   5:                 CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainerforlease");
   6:                 CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(FileUpload1.FileName);
   7:                 blockBlob.UploadFromStream(FileUpload1.FileContent);
   8:             }
   9:             catch (Exception ex)
  10:             {
  11:                 ErrorMsg.Text = ex.Message;
  12:             }

删除文件代码:

   1: try
   2:             {
   3:                 CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
   4:                 Uri uri = e.Keys[0] as Uri;
   5:                 CloudBlockBlob blob = new CloudBlockBlob(uri, storageAccount.Credentials);
   6:                 blob.Delete();
   7:                 BindGridView();
   8:                 ErrorMsg.Text = "";
   9:             }
  10:             catch (Exception ex)
  11:             {
  12:                 ErrorMsg.Text = ex.Message;
  13:             }

Acquire lease:

   1: string selectValue = Request.Form.Get("selectRadioButton");
   2: if (!string.IsNullOrEmpty(selectValue))
   3: {
   4:     try
   5:     {
   6:         CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
   7:         CloudBlockBlob blockBlob = new CloudBlockBlob(new Uri(selectValue), storageAccount.Credentials);
   8:         string leaseId = "";
   9:         if (!string.IsNullOrEmpty(LeaseId.Text))
  10:         {
  11:             leaseId = LeaseId.Text;
  12:         }
  13:         else
  14:         {
  15:             leaseId = Guid.NewGuid().ToString();
  16:         }
  17:         blockBlob.AcquireLease(TimeSpan.FromSeconds(double.Parse(LeaseTimeSpan.Text)), leaseId);
  18:         LeaseId.Text = leaseId;
  19:         ErrorMsg.Text = "";
  20:     }
  21:     catch (Exception ex)
  22:     {
  23:         ErrorMsg.Text = ex.Message;
  24:     }
  25: }

Release lease:

   1: string selectValue = Request.Form.Get("selectRadioButton");
   2: if (!string.IsNullOrEmpty(selectValue))
   3: {
   4:     try
   5:     {
   6:         CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
   7:         CloudBlockBlob blockBlob = new CloudBlockBlob(new Uri(selectValue), storageAccount.Credentials);
   8:  
   9:         blockBlob.ReleaseLease(AccessCondition.GenerateLeaseCondition(LeaseId.Text));
  10:         ErrorMsg.Text = "";
  11:     }
  12:     catch (Exception ex)
  13:     {
  14:         ErrorMsg.Text = ex.Message;
  15:     }
  16: }

Renew Lease:

   1: string selectValue = Request.Form.Get("selectRadioButton");
   2: if (!string.IsNullOrEmpty(selectValue))
   3: {
   4:     try
   5:     {
   6:         CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
   7:         CloudBlockBlob blockBlob = new CloudBlockBlob(new Uri(selectValue), storageAccount.Credentials);
   8:         blockBlob.RenewLease(AccessCondition.GenerateLeaseCondition(LeaseId.Text));
   9:  
  10:         ErrorMsg.Text = "";
  11:     }
  12:     catch (Exception ex)
  13:     {
  14:         ErrorMsg.Text = ex.Message;
  15:     }
  16: }

Break Lease:

   1: string selectValue = Request.Form.Get("selectRadioButton");
   2: if (!string.IsNullOrEmpty(selectValue))
   3: {
   4:     try
   5:     {
   6:         CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
   7:         CloudBlockBlob blockBlob = new CloudBlockBlob(new Uri(selectValue), storageAccount.Credentials);
   8:         blockBlob.BreakLease();
   9:         ErrorMsg.Text = "";
  10:     }
  11:     catch (Exception ex)
  12:     {
  13:         ErrorMsg.Text = ex.Message;
  14:     }
  15: }

 

首先,我们来给Blob上锁(Acquire lease),如图所示,过期时间设置为60s(如果过期时间设置为-1,即Lease永不过期):

然后我们尝试删除该Blob文件,如图所示,出现了异常:

执行Release lease以后,再来删除文件,OK,文件已经成功删除。

点击 这里 下载源码。有兴趣的朋友可以根据源码自己做其他验证。

posted on 2013-01-17 22:49  李甲蔚  阅读(2013)  评论(2编辑  收藏  举报