Cloud Service中包含两类角色:WebRole和WorkerRole。这些Roles们可以理解为不同的虚拟机,唯一的区别即为:WebRole用来寄宿Web站点,可以把它理解为一台安装了IIS的虚拟机。WorkerRole能用来寄宿后台服务,例如:windows 服务神马的。初步看来,我们是可以用Cloud Service快速的打造N层架的商业程序,什么3层,4层什么的。
本文将会介绍一个小例子,如何使用Cloud Service搭建一个三层架构的Web站点。这站点的功能十分的简单:1)在Web页面上显示保存在Azure Sql Server中的记录,2)通过 Service Bus Queue 向 WorkerRole处理程序发生Mesage, 3)WorkerRole接受到Queue中的Message后并将消息中保存的记录插入到Azure Sql Server中。
工程代码结构
WebRole和WorkerRole工程结构
程序功能
WebRole实现代码
Aspx
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>Customer Information Management</h1>
<p>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:gbsql01ConnectionString %>" SelectCommand="select * from customers"></asp:SqlDataSource>
<asp:ListView ID="ListView1" runat="server" DataKeyNames="Id" DataSourceID="SqlDataSource1" InsertItemPosition="LastItem" OnItemInserting="ListView1_ItemInserting" OnItemUpdating="ListView1_ItemUpdating">
<AlternatingItemTemplate>
<tr style="background-color: #FAFAD2;color: #284775;">
<td>
<asp:Label ID="IdLabel" runat="server" Text='<%# Eval("Id") %>' />
</td>
<td>
<asp:Label ID="NameLabel" runat="server" Text='<%# Eval("Name") %>' />
</td>
<td>
<asp:Label ID="EmailLabel" runat="server" Text='<%# Eval("Email") %>' />
</td>
</tr>
</AlternatingItemTemplate>
<EditItemTemplate>
<tr style="background-color: #FFCC66;color: #000080;">
<td>
<asp:Button ID="UpdateButton" runat="server" CommandName="Update" Text="Update" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="Cancel" />
</td>
<td>
<asp:Label ID="IdLabel1" runat="server" Text='<%# Eval("Id") %>' />
</td>
<td>
<asp:TextBox ID="NameTextBox" runat="server" Text='<%# Bind("Name") %>' />
</td>
<td>
<asp:TextBox ID="EmailTextBox" runat="server" Text='<%# Bind("Email") %>' />
</td>
</tr>
</EditItemTemplate>
<EmptyDataTemplate>
<table runat="server" style="background-color: #FFFFFF;border-collapse: collapse;border-color: #999999;border-style:none;border-width:1px;">
<tr>
<td>No data was returned.</td>
</tr>
</table>
</EmptyDataTemplate>
<InsertItemTemplate>
<tr style="">
<td>
<asp:Button ID="InsertButton" runat="server" CommandName="Insert" Text="Insert" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="Clear" />
</td>
<td>
<asp:TextBox ID="IdTextBox" runat="server" Text='<%# Bind("Id") %>' />
</td>
<td>
<asp:TextBox ID="NameTextBox" runat="server" Text='<%# Bind("Name") %>' />
</td>
<td>
<asp:TextBox ID="EmailTextBox" runat="server" Text='<%# Bind("Email") %>' />
</td>
</tr>
</InsertItemTemplate>
<ItemTemplate>
<tr style="background-color: #FFFBD6;color: #333333;">
<td>
<asp:Label ID="IdLabel" runat="server" Text='<%# Eval("Id") %>' />
</td>
<td>
<asp:Label ID="NameLabel" runat="server" Text='<%# Eval("Name") %>' />
</td>
<td>
<asp:Label ID="EmailLabel" runat="server" Text='<%# Eval("Email") %>' />
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table runat="server">
<tr runat="server">
<td runat="server">
<table id="itemPlaceholderContainer" runat="server" border="1" style="background-color: #FFFFFF;border-collapse: collapse;border-color: #999999;border-style:none;border-width:1px;font-family: Verdana, Arial, Helvetica, sans-serif;">
<tr runat="server" style="background-color: #FFFBD6;color: #333333;">
<th runat="server">Id</th>
<th runat="server">Name</th>
<th runat="server">Email</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</td>
</tr>
<tr runat="server">
<td runat="server" style="text-align: center;background-color: #FFCC66;font-family: Verdana, Arial, Helvetica, sans-serif;color: #333333;"></td>
</tr>
</table>
</LayoutTemplate>
<SelectedItemTemplate>
<tr style="background-color: #FFCC66;font-weight: bold;color: #000080;">
<td>
<asp:Label ID="IdLabel" runat="server" Text='<%# Eval("Id") %>' />
</td>
<td>
<asp:Label ID="NameLabel" runat="server" Text='<%# Eval("Name") %>' />
</td>
<td>
<asp:Label ID="EmailLabel" runat="server" Text='<%# Eval("Email") %>' />
</td>
</tr>
</SelectedItemTemplate>
</asp:ListView>
</p>
</asp:Content>
Aspx.cs
private void SendAddCustomerMsg(Hashtable item)
{
NamespaceManager nm = NamespaceManager.Create();
QueueClient client = QueueClient.Create("jeffqueue",ReceiveMode.ReceiveAndDelete);
BrokeredMessage msg = new BrokeredMessage(item);
try
{
client.Send(msg);
}
catch
{
throw;
}
finally
{
client.Close();
}
}
protected void ListView1_ItemInserting(object sender, ListViewInsertEventArgs e)
{
Hashtable item = new Hashtable();
item.Add("Id", e.Values["Id"]);
item.Add("Name", e.Values["Name"]);
item.Add("Email", e.Values["Email"]);
SendAddCustomerMsg(item);
e.Cancel = true;
}
WorkerRole实现代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Linq;
using System.Net;
using System.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.Storage;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;
namespace gbworkerrole1
{
public class WorkerRole : RoleEntryPoint
{
NamespaceManager nm;
QueueClient client;
public override void Run()
{
// This is a sample worker implementation. Replace with your logic.
Trace.TraceInformation("gbworkerrole1 entry point called", "Information");
while (true)
{
BrokeredMessage msg = client.Receive(TimeSpan.FromSeconds(5));
if (msg != null)
{
SqlConnection conn = new SqlConnection("Data Source=gaalnvmd7w.database.windows.net;Initial Catalog=gbsql01;Persist Security Info=True;User ID=account;Password=pwd");
SqlCommand cmd = new SqlCommand("insert into customers values(@id,@name,@email)", conn);
Hashtable item = msg.GetBody<Hashtable>();
cmd.Parameters.AddWithValue("@Id", item["Id"]);
cmd.Parameters.AddWithValue("@Name", item["Name"]);
cmd.Parameters.AddWithValue("@Email", item["Email"]);
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch { }
finally {
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
}
}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
nm = NamespaceManager.Create();
client = QueueClient.Create("jeffqueue", ReceiveMode.ReceiveAndDelete);
return base.OnStart();
}
public override void OnStop()
{
client.Close();
base.OnStop();
}
}
}