使用Windows Azure Drive
本文是 Windows Azure 入门教学 的第八篇文章。
本文将会介绍如何使用 Windows Azure Drive。
我们知道,由于云端的特殊性,通常情况下,对文件系统的读写建议使用 Blob Storage来代替。这就产生了一个问题:对于一个已经写好的本地应用程序,其中使用了 NTFS API对本地文件系统读写的代码是否需要进行完全重写以便迁移到 Windows Azure平台上呢?答案是否定的。 Windows Azure平台提供了 Drive的功能。
在 1.1版本的 SDK中提供了 CloudDrive类,能够将本地 NTFS文件系统 Mount到 Blob Storage上。我们只要添加一小段代码来表明我们希望 Mount Drive到 Blob Storage上就能重用大部分已有的对本地文件系统访问的代码。这样,我们已有的程序能够无缝地迁移到 Windows Azure上而不需要做大的改动。
在开始本教学之前,请确保你从Windows Azure 平台下载 下载并安装了最新的 Windows Azure开发工具。 本教学使用 Visual Studio 2010作为开发工具。
步骤一:创建解决方案和项目
由于我们要在本地模拟环境下测试 Windows Azure Drive,首先,请确保 Storage Emulator已经启动。我们可以找到管理器的进程手动启动或者让 Visual Studio 2010帮助我们启动他。
右击工具栏中 Windows Azure模拟器的图标,选择” Show Storage Emulator UI”。弹出如下图所示的窗口:
我们要关注的是 Service management中 Blob所在的一行。要确保 Status为 Running。
确认完毕后启动 Visual Studio 2010,新建一个 Cloud Service项目并为之添加一个 Web Role。
步骤二:添加 SDK 程序集引用
请在项目属性页里确认项目的 Target framework的值是 .NET Framework 4或 .NET Framework 3.5。然后在 Web Role项目中添加对 C:/Program Files/Windows Azure SDK/v1.3/ref/Microsoft.WindowsAzure.CloudDrive.dll的引用。该路径为 SDK默认安装路径,如果你不能在这个路径中找到 Microsoft.WindowsAzure.CloudDrive.dll请从 SDK安装路径中寻找。
步骤三:添加代码
删除并重新创建 Default.aspx 页面,然后在 Default.aspx.cs中引用命名空间:
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.IO;
然后添加下列代码:
public partial class Default : System.Web.UI.Page
{
string _driveLetter = WebRole .DriveLetter;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Bind();
}
}
void Bind()
{
// 显示被 Mount 的 Drive 根目录下的所有文件
DirectoryInfo di = new DirectoryInfo (string .Format("{0}//" , _driveLetter));
this .GridView1.DataSource = di.GetFiles();
this .GridView1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
// 在被 Mount 的 Drive 根目录下保存文件
if (this .FileUpload1.HasFile)
{
File .WriteAllBytes(string .Format("{0}//{1}" , _driveLetter, this .FileUpload1.FileName), this .FileUpload1.FileBytes);
Bind();
}
}
}
在 Default.aspx中添加下列代码:
< form id ="form1" runat ="server">
< asp : FileUpload ID ="FileUpload1" runat ="server" />
< asp : Button ID ="Button1" runat ="server" Text ="Upload" onclick ="Button1_Click" />
< asp : GridView AllowPaging ="true" PageSize ="20" ID ="GridView1" runat ="server">
</ asp : GridView >
</ form >
接下来在 WebRole.cs中引用命名空间:
using Microsoft.WindowsAzure.StorageClient;
然后添加下列代码:
public class WebRole : RoleEntryPoint
{
public static string DriveLetter { get ; private set ; }
CloudDrive myCloudDrive;
public override bool OnStart()
{
// 当用配置文件中 ConfigurationSettings 时必须调用 CloudStorageAccount.SetConfigurationSettingPublisher
// 来说明当配置文件在发布后被更改时将采取何种操作
CloudStorageAccount .SetConfigurationSettingPublisher((configName, configSetter) =>
{
configSetter(RoleEnvironment .GetConfigurationSettingValue(configName));
RoleEnvironment .Changed += (sender, arg) =>
{
if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange >()
.Any((change) => (change.ConfigurationSettingName == configName)))
{
if (!configSetter(RoleEnvironment .GetConfigurationSettingValue(configName)))
{
RoleEnvironment .RequestRecycle();
}
}
};
});
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
return base .OnStart();
}
public override void Run()
{
CloudStorageAccount storageAccount = CloudStorageAccount .FromConfigurationSetting("DataConnectionString" );
LocalResource localCache = RoleEnvironment .GetLocalResource("InstanceDriveCache" );
CloudDrive .InitializeCache(localCache.RootPath, localCache.MaximumSizeInMegabytes);
// 检查 Container 是否存在,不存在则创建
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
blobClient.GetContainerReference("drives" ).CreateIfNotExist();
// 创建 Cloud Drive
myCloudDrive = storageAccount.CreateCloudDrive(
blobClient
.GetContainerReference("drives" )
.GetPageBlobReference("mydrive.vhd" )
.Uri.ToString()
);
try
{
myCloudDrive.Create(64);
}
catch (CloudDriveException )
{
}
DriveLetter = myCloudDrive.Mount(0, DriveMountOptions .Force);
base .Run();
}
public override void OnStop()
{
myCloudDrive.Unmount();
base .OnStop();
}
}
最后,修改配置文件。在 Cloud Service项目的 ServiceConfiguration.cscfg中添加下列配置:
<? xml version = "1.0 " encoding = "utf-8 "?>
< ServiceConfiguration serviceName = "WindowsAzureDriveDemonstration "xmlns = "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration " osFamily = "1 " osVersion = "* ">
< Role name = "WebRole1 ">
< Instances count = "1 " />
< ConfigurationSettings >
< Setting name = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString " value = "UseDevelopmentStorage=true " />
< Setting name = "DataConnectionString " value = "UseDevelopmentStorage=true " />
</ ConfigurationSettings >
</ Role >
</ ServiceConfiguration >
在 ServiceDefinition.csdef中添加下列配置(注意将 Sites部分的内容删除或注释掉):
<? xml version = "1.0 " encoding = "utf-8 "?>
< ServiceDefinition name = "WindowsAzureDriveDemonstration " xmlns = "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition ">
< WebRole name = "WebRole1 ">
< Sites >
< Site name = "Web ">
< Bindings >
< Binding name = "Endpoint1 " endpointName = "Endpoint1 " />
</ Bindings >
</ Site >
</ Sites >
< Endpoints >
< InputEndpoint name = "Endpoint1 " protocol = "http " port = "80 " />
</ Endpoints >
< Imports >
< Import moduleName = "Diagnostics " />
</ Imports >
< LocalResources >
< LocalStorage name = "InstanceDriveCache " cleanOnRoleRecycle = "false " sizeInMB = "300 " />
</ LocalResources >
< ConfigurationSettings >
< Setting name = "DataConnectionString " />
</ ConfigurationSettings >
</ WebRole >
</ ServiceDefinition >
步骤四:观察并分析代码
步骤三中的代码中, Default.aspx.cs的代码跟普通的 ASP.NET项目代码没什么区别。我们把盘符抽离出来以便迁移到 Windows Azure上。 Default.aspx.cs中的代码跟 Windows Azure唯一相关的一句语句就是 string driveLetter = WebRole .DriveLetter 。 我们如果把 WebRole .DriveLetter 替换为本机盘符该 ASP.NET程序将能够正常运行。
后面的代码示范了如何 Mount Drive到 Blob Storage。此外我们使用了本地缓存来缓存尚未被传递到 Blob Storage的文件。
通过上面的例子可以看到,只需额外添加一小段代码,已有的使用 NTFS API的程序能够很方便地迁移到 Windows Azure平台上。
步骤五:运行程序
运行程序。上传几个文件。如果一切顺利你将看到下图所示的结果。可以看到文件的 DirectoryName为“ a:/”。这就是被 Mount到 Blob Storage上的 Drive的盘符。
需要注意的是,本例中我们并未修改 WebRole的实例数,因此只有 1个 WebRole(发布到云端后将只有一个虚拟机被使用)。如果有两个实例,并且要让两个实例共享一个”网络硬盘“的话,本例中代码将不能正常工作。因为对于同一个 Blob同时只能有一个虚拟机 Mount。一个可能的解决方案是额外维护一个 Web Service来管理 Mount和 UnMount Drive。进一步的讨论超出了本教学的范围。有兴趣的读者可以下载并参考 Windows Azure Cloud Drive白皮书 获取信息。