深入了解 Windows Azure
Windows 8 和 Windows Azure: 云中的融合
Bruno Terkaly
Ricardo Villalobos
几乎可以肯定的是,当今的软件开发人员必须接纳云技术以便创建引人注目的 Windows 应用商店应用程序 — 庞大的用户和设备数目让这一点不言自明。超过三分之一的地球人口连接到 Internet,而现在访问在线资源的设备数目比人数还多。此外,移动数据通信量在 2011 年增加了 1.3 倍,这是连续第四年增长超过 1 倍。无论怎么看,您最后都会得出一个非常简单的结论: 新型应用程序要求与云的连接。
云计算的价值主张很有吸引力。大多数的观察人士都指出,按需可伸缩性以及仅为您使用的内容付费吸引着大家采用云。但是,在这个需要多个设备互连的世界中,云实际上也提供一些重要技术。Windows 应用商店应用程序用户(很可能在使用多种应用程序和多个设备)期望集中地放置其数据。如果他们在 Windows Phone 设备上保存数据,则这些数据还应立即可用于其平板或任何其他设备上,包括 iOS 和 Android 设备。
Windows Azure 是 Microsoft 的公共云平台,提供最大的全球覆盖面以及最全面的服务后端。它支持使用多种操作系统、语言、数据库和工具选项,提供自动的操作系统和服务修补。该基础的网络体系结构提供自动的负载平衡以及抵御硬件故障的能力。最后但并不容忽视的一点是,Windows Azure 支持开发人员无需停机便可以升级应用程序的部署模型。
在本文中展示的 Web 服务应用程序在几分钟内就可以在一个或多个 Microsoft 的全球云数据中心中托管。无论您是构建任务列表应用程序、游戏还是业务线会计应用程序,都可以利用本文中介绍的技术来支持依赖于永久或偶尔连接的客户端的情况。
您将学到的内容
首先,我们将介绍如何在 Windows Azure 上构建一个简单的云托管服务以便支持异步客户端,而与正在手机、平板、笔记本电脑或台式机上正运行的设备类型无关。然后,我们将展示如何从 Windows 应用商店应用程序轻松地调用 Web 服务以便检索数据。
一般来说,有两种可使数据为 Windows 应用商店应用程序所用的方法。本文将着重介绍用于检索数据的“提取方法”,在这个方法中,需要通过 HTTP Web 调用运行应用程序和发出数据请求。该提取方法通常利用开放标准(HTTP、JSON、具像状态传输 [REST]),并且来自不同供应商的大多数设备类型(如果不是全部类型)都可以利用该方法。
在本文中我们将不会涵盖“推送方法”。此方法依赖于 Windows 推送通知服务 (WNS),它允许云托管的服务将未经请求的数据发送到 Windows 应用商店应用程序。此类应用程序无需在前台运行,因此不能保证消息传递。有关使用 WNS 的信息,请参阅 bit.ly/RSXomc。
两种项目
完整解决方案要求两个主要组件: 服务器端或 Web 服务项目(可在内部部署或在 Windows Azure 中部署);以及客户端项目,由基于新的 Windows UI 的 Windows 应用商店应用程序构成。这两种项目都可以使用 Visual Studio 2012 创建。
基本上,有两个用于构建 Web 服务项目的选项: Windows Communication Foundation (WCF) 或 ASP.NET Web API(在 ASP.NET MVC 4 中随附)。因为与通过 WCF 公开服务有关的论述很多,所以,对于我们的方案,我们将使用 ASP.NET Web API 所提供的更现代的方法,真正采用 HTTP 概念(URI 和谓词)。此外,该框架允许您创建使用更先进的 HTTP 概念(例如请求/响应头和超媒体构造)的服务。
这两种项目都可以在开发过程中在单台计算机上测试。您可以在 archive.msdn.microsoft.com/mag201210AzureInsider 下载整个解决方案。
您需要什么
最显而易见的起始点就是需要 Windows 8,并且不足为奇的是,项目应该使用最新版本的 Visual Studio 创建,该版本可以从 bit.ly/win8devtools 下载。
对于服务器端项目,您将需要最新的 Windows Azure SDK,这包括用于从 Visual Studio 内创建云项目的必需的程序集和工具。您可以从 bit.ly/NlB5OB 下载此 SDK 和相关工具。您还将需要一个 Windows Azure 帐户。可以从 bit.ly/azuretestdrive 下载免费试用版。
过去,一直使用 SOAP 来构建 Web 服务,但本文将主要针对 REST 样式的体系结构。简言之,REST 更易于使用、工作负荷更低并且无需特殊工具。
开发人员在构建 Web 服务时还必须选择数据交换格式。该选择通常介于 JSON 和 XML 之间。JSON 使用基于 JavaScript 语言的压缩数据格式。它通常称作 XML 的“轻型替代品”,因为它具有少得多的语法并且直接映射到在客户端应用程序中使用的数据结构。我们将在示例中使用 JSON 数据。
作出了这些决定后,我们可以创建 Web 服务了。我们的目标是构建一个基于 HTTP 的服务,该服务可以接触可能的范围最广的客户端,包括浏览器和移动设备。
构建 Web 服务
首先,我们将以管理员身份启动 Visual Studio 2012。下面是使用 ASP.NET MVC 4 Web API 创建服务器端 Web 服务的步骤:
- 单击“文件”菜单并选择“新建”|“项目”(参见图 1)。
- 为模板类型选择 Visual C# | Web。
- 在顶部的下拉列表中选择 .NET Framework 4。
- 选择 ASP.NET MVC 4 Web 应用程序。
- 输入名称 WebService 以及您选择的位置。
- 单击“确定”。
- 向导将要求您选择“项目模板”。选择 Web API 并且确保视图引擎为 Razor(默认设置),如图 2 中所示。
- Visual Studio 将生成多种文件。这么多的文件可能令人无所适从,但我们只需考虑几个文件,如图 3 中所示。
图 1“新建项目”对话框
图 2“项目模板”对话框
图 3 用于 WebService 的解决方案资源管理器
ValuesController.cs 很重要,因为它包含在 Windows 8 客户端针对 Web 服务提交 HTTP 请求时将执行的代码。我们将在此处添加代码以便返回 Windows 应用商店应用程序要求的 JSON 数据。ValuesController 类(如图 4 中所示)由 Visual Studio 生成并且继承自 ApiController,它将返回序列化并发送到客户端的数据,并且自动采用 JSON 格式。
图 4 ValuesController 类
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
请注意,图 4 中的方法(Get、Post、Put 和 Delete)对应特定的创建、读取、更新和删除 (CRUD) 操作以及 Windows 应用商店应用程序执行的 HTTP 谓词。 下面是 ASP.NET Web API 框架的优点: 它自动将客户端使用的 HTTP 谓词直接路由到在 ValuesController 类中定义的方法,尽量避免发生编程错误。
WebService 项目是现成的,可供您运行。 ValuesController 类中的方法是自记录的:
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
请注意,在客户端使用 URL http://localhost:[port]/api/values 发出 HTTP 谓词 Get 时,将调用 Get 方法。 出于本演示的目的,代码将基于从 Web 服务返回的颜色绘制同心圆。 按如下所示修改前面的代码:
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "#0000FF", "#000000", "#FF0000",
"#FFFF00", "#00FF00" };
}
您可以看到,我们现在将返回不同颜色的字符串的数组。 我们创建的这个 Windows 应用商店应用程序将这些字符串呈现为实际颜色,具体来说是呈现为带颜色的同心圆。
使用浏览器进行测试
在创建 Windows 应用商店应用程序之前对 Web 服务进行测试始终是个好主意。 使用您喜爱的任何浏览器。
若要从浏览器测试 Web 服务,请执行以下步骤:
- 在 Visual Studio 中,单击“调试”菜单,然后选择“开始调试”。
- 您应该看到默认的开始页,如图 5 中所示。
- 请注意,Visual Studio 将选择任意端口,在这个例子中是 58428。 您的 Visual Studio 实例使用的端口将可能不同。
- 您可能记得,我们需要将“api/values”添加到 URL,以便 Get 方法得到调用,这意味着最终的 URL(在我们的例子中)应该是 http://localhost:58428/api/values。 这是 Visual Studio 创建您的项目时的内置功能。 您可以根据自身需要更改此映射。
- 转到 Visual Studio 的地址栏,然后键入 http://localhost:58428/api/values。 请记住用您自己的值替换该端口号。
- 将显示一个对话框,如图 6 中所示。
- 单击“保存”按钮,然后在记事本中打开 values.json。
- 记事本将显示返回的值。 请注意,在图 7 中,返回的数据自动采用 JSON 格式,并且遵循 ASP.NET Web API 架构。
图 5 使用 Internet Explorer 对 Web 服务进行测试
图 6 Internet Explorer 对话框
图 7 Web 服务返回的 JSON 数据
进入 Windows 8
现在,我们已成功地从我们的 Web 服务返回了 JSON 数据,让我们看一下如何从 Windows 应用商店应用程序使用这些数据。 我们的目标是为了从 Web 服务读取颜色并且基于 Web 服务返回的值绘制同心圆。 我们的最终 Windows 应用商店应用程序应该生成类似图 8 的图像。 您看到的颜色已由该 Web 服务定义。 如果该 Web 服务更改返回的颜色,则 Windows 应用商店应用程序会将这些颜色作为您在图 8 中看到的同心圆反映出来。
图 8 正在运行的 Windows 应用商店应用程序
您可以与在 Web 服务项目相同的解决方案中创建 Windows 应用商店应用程序,也可以开始专用于 Windows 8 客户端的新的 Visual Studio 实例。 我们将以 Windows 应用商店应用程序管理员的身份开始 Visual Studio 的一个新实例。 为此,请执行以下步骤(见图 9):
图 9“新建项目”对话框
- 以管理员身份开始 Visual Studio 的第二个实例。
- 单击“文件”菜单并选择“新建”|“项目”。
- 为模板类型选择 Visual C# | Windows 应用商店。
- 在顶部的下拉列表中选择 .NET Framework 4.5。
- 选择空应用程序 (XAML)。
- 输入名称 Windows8Client 以及您选择的位置。
- 单击“确定”。
在您完成这些步骤后,导航到“视图”菜单并且选择解决方案资源管理器(参见图 10),然后打开文件 MainPage.xaml.cs。
图 10 用于 Windows8Client 的解决方案资源管理器
调用 Web 服务
我们已准备好,可以添加将从 Windows 应用商店应用程序调用 Web 服务的代码。 该 Windows 应用商店应用程序将对该 Web 服务发出一个 Web 请求。
为了支持 Web 请求,将按如下所示对 MainPage.xaml.cs 进行修改:
- 将为内置 Grid 控件添加一个 Loaded 事件。
- 该 Loaded 事件将提交一个 Web 请求以便调用该 Web 服务。 HttpClient 类将用于此目的。
- 为了将颜色字符串从该 Web 服务转换为真正的颜色,将添加一个名为 CircleColorFromString 的方法。
- 为了绘制同心圆,我们将添加称作 AddCircle 的方法。
执行以下步骤以便对该 Web 服务发出一个 Web 请求:
- 右键单击 MainPage.xaml 并且选择“视图设计器”。
- 按如下所示添加 GridLoadedEvent 和 Canvas 控件(该画布将用来绘制圆形):
<Grid Name="maingrid"
Background="{StaticResource
ApplicationPageBackgroundThemeBrush}"
Loaded="GridLoadedEvent">
<Canvas Name="myCanvas" Background="White"/>
</Grid>
- 3. 双击 MainPage.xaml.cs。 MainPage.xaml.cs 的代码隐藏将出现。
- 4. 为了支持要添加的代码所要求的不同命名空间,在 MainPage.xaml.cs 的顶部包含以下引用:
using System.Net.Http; // for HttpClient()
using Windows.Data.Json; // for parsing JSON Array data
using Windows.UI.Xaml.Shapes; // for the Ellipse object
using Windows.UI // for the Color class
- 5. 添加支持例程以便绘制圆形并且对 Web 服务所发送的 JSON 字符串数据进行分析。 按图 11 中所示编辑 MainPage.xaml.cs 中的代码。
图 11 MainPage.xaml.cs
public sealed partial class MainPage : Page
{
// [ Generated code omitted for brevity ]
private void AddCircle(Color color, int diameter, int t, int l)
{
//
// Build a circle using the attributes provided as parameters.
//
Ellipse newColoredCircle = new Ellipse();
newColoredCircle.Fill = new SolidColorBrush(color);
newColoredCircle.StrokeThickness = 1;
newColoredCircle.Stroke = new SolidColorBrush(color);
newColoredCircle.Width = diameter;
newColoredCircle.Height = diameter;
//
// Add the circle to the Canvas control.
//
myCanvas.Children.Add(newColoredCircle);
Canvas.SetTop(newColoredCircle, t);
Canvas.SetLeft(newColoredCircle, l);
}
Color CircleColorFromString(string rgb)
{
//
// Convert the string-based hex values
// into a Color object and return to caller.
//
Color ringColor = new Color();
byte a = 255;
byte r = (byte)(Convert.ToUInt32(rgb.Substring(1, 2), 16));
byte g = (byte)(Convert.ToUInt32(rgb.Substring(3, 2), 16));
byte b = (byte)(Convert.ToUInt32(rgb.Substring(5, 2), 16));
ringColor = Color.FromArgb(a, r, g, b);
return ringColor;
}
private async void GridLoadedEvent(object sender,
RoutedEventArgs e)
{
//
// Retrieve colors from Web service.
//
var client = new HttpClient();
client.MaxResponseContentBufferSize = 1024 * 1024;
//
// Asynchronously call into the Web service.
//
var response = await client.GetAsync(
new Uri("http://localhost:58428/api/values"));
var result = await response.Content.ReadAsStringAsync();
//
// Parse the JSON data
//
var parsedResults = JsonArray.Parse(result);
//
// Build concentric circles, repeating colors as needed
//
const double startingPercentage = 1.0;
const double desiredCircleCount = 50.0;
for (int i = 0; i < desiredCircleCount; i++)
{
Color circleColor = CircleColorFromString(
parsedResults[i % parsedResults.Count].GetString());
int circleDiameter = Convert.ToInt32((startingPercentage –
(i / desiredCircleCount)) * this.RenderSize.Width / 2.0);
int top = Convert.ToInt32((this.RenderSize.Height -
circleDiameter)/2.0);
int left = Convert.ToInt32((this.RenderSize.Width -
circleDiameter)/2.0);
AddCircle(circleColor, circleDiameter, top, left);
}
}
}
现在对该应用程序进行测试,这相当简单:
- 返回到 Visual Studio 中的 WebService 项目,并且从“调试”菜单中选择“开始调试”。
- 确认浏览器已启动。 您现在已经准备好启动 Windows8Client 应用程序了。
- 返回到 Visual Studio 中的 Windows8Client 项目,并且从“调试”菜单中选择“开始调试”。
- 确认该 Windows 应用商店应用程序出现,如图 8 中所示。
将 Web 服务部署到 Windows Azure
一旦在本地创建并测试了该 Web 服务后,下一个合乎逻辑的步骤就是出于可伸缩性目的将其部署到云中。 这使您可以随着来自 Windows 8 设备的请求数目的增减,改变分配给该 Web 服务的计算能力及其成本。 Visual Studio 提供不同的方法将 ASP.NET Web API 项目部署到 Windows Azure,唯一的先决条件就是将一个云服务项目添加到该 Web 服务解决方案。 请遵循以下的步骤:
- 右键单击解决方案名称,然后选择“添加”|“新建项目”。
- 选择“Visual C#”|“云”作为项目模板(图 12)。
- 在顶部的下拉列表中选择 .NET Framework 4。
- 选择 Windows Azure 云服务 Visual C#。
- 输入名称 WindowsAzureCloudService 以及您选择的位置。
- 单击“确定”。
- 现在,返回到解决方案资源管理器。 在解决方案中找到该新项目,然后右键单击“角色”节点。 选择“添加”|“Web 角色项目”。
- 找到以前创建的 WebService 项目。 选择该项目,然后单击“确定”。
- 您现在应该看到在“角色”节点下列出的该 WebService 项目,如图 13 中所示。
- 您可以更改 WebService 角色的不同部署参数,再将其部署到 Windows Azure,例如要在其中进行托管的虚拟机 (VM) 的大小和支持它的实例的数目。 若要查看这些参数,请右键单击 WebService 角色节点并选择“属性”。 将显示类似图 14 中所示的对话框。 对实例计数和 VM 大小参数要特别注意,因为这两个参数将确定部署了角色后的使用率。 有关针对计算实例的 Windows Azure 价格的更多信息,请访问 bit.ly/SnLj68。
- 右键单击 WindowsAzureCloudService 项目,然后选择“包”。 对于“服务”和“生成”配置参数保持默认选择,然后单击“包”按钮。 该操作将生成两个文件: WindowsAzureCloudService.cspkg 和 ServiceConfiguration.Cloud.cscfg,需要使用这两个文件通过端口在 Windows Azure 上创建云服务。 请注意,项目可以直接从 Visual Studio 部署,但我们将不会在本文中介绍该方法。
- 通过打开 URL manage.windowsazure.com 登录到您的 Windows Azure 帐户,然后按照 bit.ly/R15VNj 中的说明,创建新的云服务并上载两个生成的文件。
- 根据您用于该云服务的名称,您的新 ASP.NET Web API 将在 http://{cloudservicename}.cloudapp. net/api/values 上提供。
- 将 Windows 应用商店应用程序指向该 URL,任务就完成了。
图 12 将一个云服务项目添加到 Web 服务解决方案
图 13 向云服务角色中添加 WebService 项目
图 14 用于 WebService 角色的 Windows Azure 部署属性
在云中
通过使用 ASP.NET Web API,支持以异步方式使用 REST 命令以便通过 Web 服务使用和获取数据的应用程序将非常简单。 Visual Studio 2012 和 .NET Framework 4.5 随附的库极大地简化了对 Web 服务发出异步 Web 请求的过程。 最后但并不容忽视的一点是,通过将开发环境与 Windows Azure 相集成,开发人员可以迅速将服务部分部署到云,并且充分利用云所提供的可伸缩性和遍布全球的基础结构能力。
Bruno Terkaly是 Microsoft 的开发推广人员。 他的知识深度来源于多年来相关领域以及使用大量平台、语言、框架、SDK、库和 API 编写代码的经验。 他不辞辛苦,就有关构建基于云的应用程序(特别是使用 Windows Azure 平台)编写代码、发布博客并给予现场演示。
Ricardo Villalobos 是一名资深的软件设计师,具有 15 年为供应链管理行业设计和创建应用程序的经验。 他持有数个技术证书,并获得了达拉斯大学商务管理专业的硕士学位。他是 Microsoft 的 Windows Azure CSV 孵化团队的云架构师。
衷心感谢以下技术专家对本文的审阅: Robert Green