del.icio.us Tags: ,

上一篇是关于Azure Service 的表存储,本篇来主要是针对Azure中另外一类特殊的存储-二进制等非结构化的存储,如果我们的Azure服务中有需要保存非传统或结构化的数据,如图片、声音及视频媒体等信息,那么我们就需要使用到Blob存储了。而Windows Azure平台提供了一个很不错的托管平台和编程模型。

Blob存储和Azure 表存储不同的是在概念上,之前我们看到表存储最重要的概念是实体(Entity)概念,实体里面包含属性。对应到Blob存储,对应实体,比较重要的概念是容器(Container) .

规则1Blob数据是存储在容器中的,一个容器是一类Blob数据的集合,保存了一组Blob数据,容器本身有共享读取和私有不同的访问的策略;每个容器都关联一个元数据存储对象,用来记录Blob数据相关的属性;每个容器也有一个列表,列表记录了容器中所有的Blob数据。

Blob存储容器的概念如下图:

clip_image002

Pictures source: ES04.pptx of PDC 2008-Windows Azure Storage–Essential Cloud Storage Services

帐号Sally下面有两个Blob存储容器,一个容器叫pictures,表示它是用来保存图片的;另外一个容器叫movies,表示它是用来保存视频数据的。Pictures容器中包含了两个Blob数据,分别是IMG001.jpg和IMG002.jpg。

规则2Azure的Blob存储容器也是跟随和隶属于一个帐号的,一个账号下面可以建立多个Blob存储 容器,和表存储的表名一样容器名跟随在帐号名的范围内,你可以从访问的REST路径看出规律:http://<account>.blob.core.windows.net/<container>/<blobname>

如上图,容器pictures和movies分别隶属于sally这个帐户下。

规则3Blob数据 是保存在不同的Blob存储容器中,一个Blob数据最大容量是50G,每个Blob数据在容器中有一个唯一的字符标示作为Blob数据名。每个Blob数据都可以有和它关联的属性描述,每一个属性是一个名值对,这些属性保存在容器的元数据中,在一个容器中,Blob数据的关联属性大小不能超过8K

如上图,IMG001.jpg,IMG002.jpg和MOV1.AVI是分别保存在不同容器的Blob数据,IMG001.jpg就是它的Blob数据名。

综合规则1,2,3 ,对于: http://sally.blob.core.windows.net/music/rock/rush/xanadu.mp3 这样一个访问标示,帐户名(Account)是:sally,Blob存储容器名(Container) 是:music,Blob数据名(BlobName )是:rock/rush/xanadu.mp3

规则4:上传一个Blob数据到某个Blob存储容器,如果一次上传的大小超过64M,则要进行分块(Blocks)多次上传,比如一个10G的电影,你可以分成2500个块,每个块4M大小,进行连续上传。分块后,每一个块都有一个唯一的编号或分块名称标示这个块。

有关分块相关的规则和操作场景和设计要点比较繁多,在本篇文章中不做过多的讨论。

 

接下来,我们来看一下,如何定义Blob数据容器以及Blob数据存取和访问的编程技术。操作的练习,我选用了Jim Nakashima的文章Windows Azure Walkthrough: Simple Blob Storage Sample 作为体验内容。

这个练习主要是熟悉Blob数据的创建和访问编程模型,运行后的界面如下图:

clip_image004

这个应用类似一个下载网站,你可以上传文件到Azure Blob存储中,针对每个上传的文件,上传的同时,你可以添加和文件相关的属性,将其保存到容器的元数据中。上传之后,我们会查询Blob存储容器,也可以进行删除容器中Blob数据的操作处理。基本上,覆盖了规则1,规则2和规则3的所有相关概念和理念。

由于Jim Nakashima的文章有十分详细的操作步骤,我就不一一论述操作步骤了,而是介绍重点的处理过程。

Azure 服务的Blob存储存取API,依然是采用了SDK中的StorageClient 类库,这个类库在 Azure SDK的\StorageClient\Lib 目录下。之前系列的文章已经多次说明了增加StorageClient的方法。

 

使用GetBlobContainer 和CreateContainer查询和创建Blob存储容器

   1: StorageAccountInfo accountInfo = StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration();
   2:  
   3: // Container names have the same restrictions as DNS names
   4:  
   5: BlobStorage blobStorage = BlobStorage.Create(accountInfo);
   6:  
   7: _Container = blobStorage.GetBlobContainer(RoleManager.GetConfigurationSetting("ContainerName"));
   8:  
   9: // returns false if the container already exists // Make the container public so that we can hit 
  10:  
  11: // the URLs from the web
  12:  
  13: _Container.CreateContainer(new NameValueCollection(), ContainerAccessControl.Public);
  14:  

 

上传时,增加Blob数据相关的属性(BlobProperties)

   1: // Make a unique blob name
   2:  
   3: string extension = System.IO.Path.GetExtension(fileUploadControl.FileName);
   4:  
   5: BlobProperties properties = new BlobProperties(Guid.NewGuid().ToString() + extension);
   6:  
   7: // Create metadata to be associated with the blob
   8:  
   9: NameValueCollection metadata = new NameValueCollection();
  10:  
  11: metadata["FileName"] = fileNameBox.Text;
  12:  
  13: metadata["Submitter"] = submitterBox.Text;
  14:  
  15: properties.Metadata = metadata;
  16:  
  17: properties.ContentType = fileUploadControl.PostedFile.ContentType;
  18:  
  19: // Create the blob
  20:  
  21: BlobContents fileBlob = new BlobContents(fileUploadControl.FileBytes);
  22:  
  23: _Container.CreateBlob(properties, fileBlob, true);
  24:  

 

使用ListBlobs方法读取容器中的Blob数据,以及枚举相关的属性(BlobProperties)

   1: IEnumerable<object> blobs = _Container.ListBlobs(string.Empty, false);
   2:  
   3: List<FileEntry> filesList = new List<FileEntry>();
   4:  
   5: foreach (object o in blobs)
   6:  
   7: {
   8:  
   9: BlobProperties bp = o as BlobProperties;
  10:  
  11: if (bp != null)
  12:  
  13: {
  14:  
  15: BlobProperties p = _Container.GetBlobProperties(bp.Name);
  16:  
  17: NameValueCollection fileEntryProperties = p.Metadata;
  18:  
  19: filesList.Add(new FileEntry(p.Name, bp.Uri, fileEntryProperties["FileName"], fileEntryProperties["Submitter"]));
  20:  
  21: }
  22:  
  23: }
  24:  
  25: fileView.DataSource = filesList;
  26:  

 

使用DeleteBlob方法删除具体的Blob数据

   1: if (_Container.DoesBlobExist(blobName))
   2:  
   3: {
   4:  
   5: _Container.DeleteBlob(blobName);
   6:  
   7: }
   8:  

 

从上面的体验我们依然可以发现,当我们掌握了 Azure Blob的设计理念和规则,利用StorageClient类库作为Azure服务存储访问的客户端,我们就可以操作Azure服务的各种存储类型。

同时我们也发现Azure服务的各种存储非常灵活和贴近应用场景,Blob存储操作和表存储相比,Blob存储更专注于如何保存保存Blob数据和关联的属性,而不是让开发人员去如何考虑创建Blob数据表;同样相比表存储,Blob存储在查询方面就没有强调要专门的检索性能,而更多的提供了Blob存储特有的上传和下载的操作。

另外StorageClient类库作为Azure服务存储访问的客户端,也被众多的开发人员进行利用,创造出许多小工具。比如最新的AzureBlobSync 小工具

clip_image006

我们就可以利用这个工具将本地的文件上传到我们的云端的某个帐号的Blob存储容器中,同样也可以将云端的某个文件下载到本地的计算机目录里,非常的方便。上图就是,我们利用这个工具,就可以往刚刚我们制作的应用中上传和下载文件。

同样利用我们刚刚编写的应用的Web Role端,也可以查询到我们使用AzureBlobSync上传的文件。

clip_image008

当然因为AzureBlobSync没有针对Blob 数据的属性(元数据)进行定义和操作,所以我们上传的文件都是没有相关属性的。但我们依然可以操作它,因为它在Blob 存储容器中。

我们也可以从SQL Server数据库中,看到Blob 存储的存储格式

clip_image010

通过这些工具和SQL数据库的观察,我们对Blob存储的设计就更加清晰和熟悉,这样我就可以轻松的在Azure 服务编程中应用它了。

同样我们还可以利用另外一个小工具Azure Storage Explorer来查看Azure服务的各种存储类型,比如表存储,队列存储,Blob存储,并且对里面的数据进行查询,删除等操作。

clip_image012

 

 

综上所述,我们可以对Azure的各种存储类型特色和用途做一个小的总结:

· Azure Blob存储 –提供了二进制的图片、视频,文件以及大块数据的存储服务

· Azure 表存储-主要提供了结构化的存储,用于保存Azure应有相关的状态管理,业务数据,用户数据等等

· Azure队列存储-主要是提供一个可靠的消息存储和消息服务,用于异步任务的通知以及服务间的通信。

· Azure LocalStorage存储-主要是提供一个独立的文件系统的临时存储,用于记录和保存一些临时的数据。

 

相关的示范代码可以在我的MSDN代码库中下载获得。代码在在Azure SDK and Tools Jan 2009 CTP环境下测试通过。