【IT168 专稿】本文将为大家详细介绍如何使用Azure Storage和Azure SDK打造基于云架构的应用程序。
1.简介
Windows Azure和Azure Storage为开发人员提供了一个新的可伸缩、健壮的体系结构,在提供ASP.NET应用程序常见外观的同时,还带来了许多新的特性。这种从传统的客户端-服务器架构到云模式的迁移,不仅给开发人员提供了新的选择,同时也给他们带来了许多不适的地方。而本文将为大家讲解如何构建一个多角色的云服务,该服务将使用两种新的Azure Storage服务:Tables和Queues。具体如下所示:
创建一个同时扮演Web Role和Worker Role的Windows Azure应用程序
·Azure Storage
·利用帐号信息设置配置文件
·使用Table存储和检索数据
·使用Queue向Worker Role发送消息
·使用Azure SDK StorageClient项目与Table和Queue进行交互
如果您打算亲手试验下面提供的代码,需要架设相应的开发环境,所需的软件有:
·VS 2008 SP1
·用于Visual Studio的Windows Azure(下载地址:http://www.microsoft.com/azure/sdk.mspx)
·Windows Azure SDK
切记:安装Windows Azure Tools for Visual Studio时要求Vista SP1或者更高版本;在Windows XP下是无法安装Windows Azure Tools for Visual Studio的。
下面的代码是在2009年7月的Azure的CTP下开发的,现在的版本可能已经发生了变化。如果某些功能无法使用或发生了改变,请参考新版本的最新文档。
我们建立的应用程序使用一个Web Role从用户那里取得两个数字输入,并允许用户查看这两个数字的相加结果。Worker Role将用于处理Queue消息,取得输入,并将两个输入相加,最后把结果返回到Table存储器中。虽然将Worker Role用于简单的加法有些大材小用,但是却很好地演示了打造一个可以与用户交互的、可伸缩性的云应用程序的所有的必要步骤。
2.创建Windows Azure应用程序
要想使用Visual Studio来开发Azure 项目,您必须作为管理员来运行该程序。因为调试Azure应用程序的时候,Azure工具要求使用管理员权限。
在给VS安装了有关的Azure工具之后,我们的Visual Studio中会出现一个新的项目类型选项“Cloud Service”,以及相应的模板。我们可以随意给我们的项目取名,比如这里为MyCouldService。
图1 新建云服务
当您单击OK按钮之后,Visual Studio会启动一个向导界面,我们可以在此为云服务项目添加其角色。
x
当您单击OK按钮之后,Visual Studio会启动一个向导界面,我们可以在此为云服务项目添加其角色。
添加的每个角色都会在Visual Studio Solution Explorer中创建一个单独的项目文件。在单击OK按钮之前,我们可以通过角色名称右边的画笔图标来给角色重新命名。当我们具有多个执行不同功能的Web或者Worker角色的时候,这一功能非常有用。
图2 云服务角色的创建和命名
单击OK按钮关闭向导。在Solution Explorer窗口中,您会发现,除了在向导中添加的两个角色项目外,还有三个与该云服务有关的项目。实际上,每个云服务都会带有这些附加的项目,它们存放了ServiceDefinition和ServiceConfirmation文件。这些文件控制着每一角色和Azure Storage配置启动的Azure实例的数量。
因为我们将要使用Azure Table和Queue存储器打开ServiceDefinition和ServiceConfirmation文件,并为相应的文件添加下列内容。
ServiceDefinition.csdef
ServiceConfiguration.cscfg
开发期间,AccountName和AccountSharedKey的值一直保持如上所示(当使用该开发环境的时候,您必须使用其名称和键)。这允许您在Azure Storage中访问和储藏数据的时候测试您的标识代码。
这里显示的端点的值是用于开发阶段的。为了检验我们的开发阶段的Azure存储端点,可以在系统托盘中打开Development Storage 管理窗口来调试应用程序。 如果这是您第一次启动Development Storage的话,Table 服务将被关闭,因为开发阶段的存储表尚未创建。我们将在后面介绍如何创建它们。
图3 Development Storage的首次运行
在Default.aspx中添加两个文字框和一个按钮用来收集两个值,同时还提供一个显示检索键的标签。然后,再添加一个文本框和按钮来检索计算结果,以及一个显示计算结果的标签。同时为每个按钮创建相应的单击事件处理程序。图4展示了所有的控件的布局及有关的标签。
图4 ASP.NET控件
现在,我们已经完成了应用程序的初始设置,并给它配置了Azure Storage帐号信息,以及一个用户界面。下面,我们介绍如何使用Azure Storage,以及在各种云服务角色中进行交互。
3.Windows Azure Storage
Windows Azure Storage中有三种类型的存储器可用,分别是Tables、Blobs和Queues。Blob存储器可用于存放大量的非结构化的数据块。Queue存储器用于存放Web role和Worker role之间的临时消息。最后,Table存储器用于以可伸缩的方式来存放结构数据。下面的是一个总结:
切记:Table存储器跟Azure SQL根本不是一码事,或者说它跟关系数据库模型扯不上什么关系。Table存储器不是关系式的。
Azure Storage是通过REST接口进行访问的,所以任何可以建立http请求的东西都能用来访问它。这还意味着,Table存储器可以通过ADO.NET Data Services进行访问。 值得庆幸的是,Microsoft已经在其Azure SDK中建立了一个用于跟Azure Storage交互的代码包装器。到7月份的CTP为止,安装Azure SDK之后,该项目名为StorageClient,并且位于C:\Program Files\Windows Azure SDK\v1.0\Samples\StorageClient。您可以直接把这个项目添加到自己的云服务解决方案中去,或者也可以将其编译,然后在解决方案中引用它。本例中,我们将使用StorageClient接口来使用Table和Queue存储器。
4.使用Windows Azure Table存储器
开发阶段的Table存储器与Windows Azure Storage服务中的稍有不同,例如开发阶段的Table存储器要求各个表都使用固定的方案。在完整的Azure Storage服务中的Table存储器不需要对表进行配置,并且可以向同一个表中的各个实体添加不同数量和类型的属性。关于开发版和生产版的不同之处,详情请见http://msdn.microsoft.com/en- us/library/dd320275.aspx。
为了创建表的方案和用于访问表的数据的数据服务上下文,我们需要创建两个单独的类,分别称为Calculation.cs和CalculationDataServiceContext.cs。在本项目中,这两个类已经创建,并添加一个新的、指向System.Data.Services.Client的引用。然后,将下列内容添加到相应的类中。
public class Calculation : Microsoft.Samples.ServiceHosting.StorageClient.TableStorageEntity
{
// Inheriting from TableStroageEntiry predefines the 3 necessary
// properties for storing any entity in Table storage; PartitionKey,
// RowKey and TimeStamp
public Calculation()
{
// Hardcoded for this example but can be anything; best practice
// is to assign the PartitionKey based on a value that groups
// your data to optimize search performance.
PartitionKey = "TEST";
// Unique identifier with each partition
RowKey = DateTime.Now.Ticks.ToString();
}
public int ValueOne { get; set; }
public int ValueTwo { get; set; }
public int CalcValue { get; set; }
}
CalculationDataServiceContext.cs
public class CalculationDataServiceContext : TableStorageDataServiceContext
{
public CalculationDataServiceContext(StorageAccountInfo accountInfo)
: base(accountInfo)
{ }
// Properties that return IQueryable are used by VS to create a
// table in development storage named after the property. The
// schema is defined by the public properites in the model class.
public IQueryable Calculations
{
get
{
return this.CreateQuery("Calculations");
}
}
// Method to take two input values, input them into the table storage
// and returns the RowKey so the value can be later retrieved.
public sting AddCalculation(int valueOne, int valueTwo)
{
Calculation calc = new Calculation();
calc.ValueOne = valueOne;
calc.ValueTwo = valueTwo;
this.AddObject("Calculations", calc);
this.SaveChanges();
return calc.RowKey;
}
}
成功创建这两个类之后,下一步是通过visual studio创建测试存储表。在Solution Explorer中,右键单击MyCloudService项目,并选择“create test storage tables”项。 当Visual Studio完成时,它将显示一个消息。现在,我们可以对应用程序进行调试了,打开Development Storage管理窗口,然后就能看到正在运行的Table服务。
图5 创建Table之后的Development Storage管理窗口
现在,我们可以向Default.aspx.cs文件中添加代码,以便创建新的Calculation对象,并将其保存到Table存储器。这可以通过向Page_Load方法添加代码,并启动Calculation按钮的单击事件处理程序来完成。
using Microsoft.Samples.ServiceHosting.StorageClient;
using System.Data.Services.Client;
// ...
protected void Page_Load(object sender, EventArgs e)
{
try
{
StorageAccountInfo accountInfo = StorageAccountInfo.GetAccountInfoFromConfiguration("TableStorageEndpoint");
// Not required in development since the table is created
// manually but is needed in the cloud to create the tables
// the first time.
TableStorage.CreateTablesFromModel(typeof(CalculationDataServiceContext), accountInfo);
}
catch (DataServiceRequestException ex)
{
// Unable to connect to table storage. In development
// verify the service is running. In the cloud check that
// the config values are correct.
// Handle error
}
}
protected void cmdStartCalculation_Click(object sender, EventArgs e)
{
StorageAccountInfo accountTableInfo = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration();
CalculationDataServiceContext calculationDSContext = new CalculationDataServiceContext(accountTableInfo);
lblCalculationKey.Text =
calculationDSContext.AddCalculation(int.Parse(txtValueOne.Text), int.Parse(txtValueTwo.Text));
lblCalculationKey.Visible = true;
}
当运行该应用程序时,我们可以输入两个数值,将其存入Table存储器,然后返回RowKey,以便后来之用。下一步要做的是通过Queue存储器发送一个消息,来检索这两个数值,并求和。
5.使用Windows Azure Queue存储器
为了给Work Role发送消息,我们需要首先向Default.aspx.cs文件插入代码,以便将消息添加到该Queue。这些代码需要放入Calculation对象创建和RowKey返回时的按钮单击事件中。为了能够检索正确的值进行计算,Worker Role需要知道PartitionKey和RowKey。对本例来说,PartitionKey被硬编码到TEST,所以我们只需传递RowKey即可。为了获得更加健壮的应用程序,我们应该将这两个值都传递给向Worker Role。
protected void cmdStartCalculation_Click(object sender, EventArgs e)
{
// ...
StorageAccountInfo accountQueueInfo = StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration();
QueueStorage qs = QueueStorage.Create(accountQueueInfo);
MessageQueue queue = qs.GetQueue("calculations");
if (!queue.DoesQueueExist())
queue.CreateQueue();
Message msg = new Message(lblCalculationKey.Text);
queue.PutMessage(msg);
}
接下来的一个步骤是打开WorkerRole.cs文件,添加相应代码来从Queue存储器检索消息,进行计算,并更新Table存储器中的内容。为此,需要先将WorkerRole.cs文件中的Start方法添加如下所示的代码。
using Microsoft.Samples.ServiceHosting.StorageClient;
// ...
public override void Start()
{
RoleManager.WriteToLog("Information", "Worker Process entry point called");
// Create account info objects for retrieving messages and accessing table storage
StorageAccountInfo accountTableInfo = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration();
StorageAccountInfo accountQueueInfo = StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration();
CalculationDataServiceContext calcDSContext = new CalculationDataServiceContext(accountTableInfo);
QueueStorage qs = QueueStorage.Create(accountQueueInfo);
MessageQueue queue = qs.GetQueue("calculations");
while (true)
{
Thread.Sleep(10000);
if (queue.DoesQueueExist())
{
Message msg = queue.GetMessage();
if (msg != null)
{
// Retrieve the Calculation entity from Table storage
var calc = (from c in calcDSContext.Calculations
where c.PartitionKey == "TEST"
&& c.RowKey == msg.ContentAsString()
select c).FirstOrDefault();
if (calc != null)
{
calc.CalcValue = calc.ValueOne + calc.ValueTwo;
// Update the entity with the new CalcValue
// property populated
calcDSContext.UpdateObject(calc);
calcDSContext.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);
// Need to delete the message once processed!
queue.DeleteMessage(msg);
}
}
}
}
}
现在,我们已经获得了一个具备一定功能的Worker Role了,即每隔10秒它会检查一次“calculation”队列中的消息。当它发现一个消息时,它会从Table存储器检索相应的计算实体,更新计算结果,并将新的结果写回Table存储器。最后一件事情,也是最重要的一件事情是从队列中删除消息,以防止该信息被重复索引。
6.将它们放在一起
最后,我们需要向Default.aspx.cs添加代码,以便用户检索计算结果。为此,需要向检索计算结果的按钮的单击事件处理程序中添加如下所示的代码。
protected void cmdRetrieveCalculation_Click(object sender, EventArgs e)
{
// Create account info objects for accessing table storage
StorageAccountInfo accountTableInfo = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration();
CalculationDataerviceContext calcDSContext = new CalculationDataServiceContext(accountTableInfo);
// Retrieve the Calculation entity from Table storage
Calculation calc = (from c in calcDSContext.Calculations
where c.PartitionKey == "TEST"
&& c.RowKey == txtCalculationKey.Text
select c).FirstOrDefault();
lblCalculatedValue.Text = calc.CalcValue.ToString();
lblCalculatedValue.Visible = true;
}
运行该程序,现在我们可以进行计算并检索结果了。记住,我们的这个服务每10秒才会检查一次队列,所以在检索计算结果之前需要稍等片刻。
图6 完工后的应用程序截屏
7.结束语
虽然在云中建立一个简单的加法机是一件无足轻重的事情,但是我们却可以从中了解云服务应用程序的许多重要知识:如何创建一个新的云服务,以及如何设置配置文件来使用Azure Storage,通过Table存储器检索和更新数据的方法,使用Queue存储器在云服务角色间传递消息的方式,以及如何利用Azure SDK提供的StorageClient项目迅速开发Azure Storage服务。