图 7 以 toast 形式消息显示的通知
$(document).ready(function() {
setInterval(function() {
$.ajax({
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "/SystemMessage/GetMessages",
success: function(data) {
for (msg in data) {
$.gritter.add({
title: data[msg].title,
text: data[msg].text,
sticky: false
});
}
}
})
}, 15000)
});
提交和处理购物车
在我们的示例应用程序中,我们希望使用队列存储执行的另一个关键方案是提交购物车。Hollywood Hackers 有一个第三方履行系统(Hollywood Hackers 无法在其空间有限的仓库中保留所有小工具),所以引擎需要对购物车进行一些处理。一旦引擎完成其处理,它会向用户通知队列提交一个消息,告知用户已经对购物车进行了处理(或者出现了问题)。如果处理购物车时用户处于在线状态,该用户将收到系统弹出的一个 toast 消息。如果用户不在线,则会在其下次登录到该站点时收到该弹出消息,如图 8 所示。
图 8 示例用户通知
查看原图(大图)
我们首先需要的是一些包装类,使我们可以与购物车队列交互。这些包装非常简单,如果要查看它们的源代码,可以在 CodePlex 站点上查看。
与标准 CRUD(创建、读取、更新、删除)存储库不同的是,队列中的读取操作不是单纯的读取操作。请记住,只要获取队列中的消息,必须在有限的时间内处理该消息,操作失败或删除消息都会显示处理完成。这种模式不能顺利地转换到存储库模式,所以我们已经不再借助包装类执行此操作。
现在,我们已经拥有了要与购物车队列交互的代码,我们可以将一些代码放在购物车控制器中,以便将购物车内容提交到队列中(请参见图 9)。
图 9 向队列提交购物车
public ActionResult Submit()
{
ShoppingCartMessage cart = new ShoppingCartMessage();
cart.UserName = User.Identity.Name;
cart.Discounts = 12.50f;
cart.CartID = Guid.NewGuid().ToString();
List<ShoppingCartItem> items = new List<ShoppingCartItem>();
items.Add(new ShoppingCartItem()
{ Quantity = 12, SKU = "10000101010",
UnitPrice = 15.75f });
items.Add(new ShoppingCartItem()
{ Quantity = 27, SKU = "12390123j213",
UnitPrice = 99.92f });
cart.CartItems = items.ToArray();
cartQueue.AddMessage(cart);
return View();
}
在实际情况下,您可能会从进程外状态(例如会话存储、缓存或窗体发布)获得购物车。为了简化本文代码,我们仅仅构建了购物车的内容。
最后,购物车内容已处于队列中,我们可以修改工作者角色,以便它可以定期检查队列中挂起的购物车。它每次会从队列中选择一个购物车,用整整一分钟对该购物车进行处理,然后向用户通知队列提交一个消息,告知用户已经对该购物车进行了处理(请参见图 10)。
图 10 检查队列中挂起的购物车
private void ProcessShoppingCarts()
{
CloudQueueMessage cqm = cartQueue.GetMessage();
while (cqm != null)
{
ShoppingCartMessage cart =
QueueMessageBase.FromMessage<ShoppingCartMessage>(cqm);
toastRepository.AddNotification(new UserTextNotification()
{
MessageText = String.Format
("Your shopping cart containing {0} items has been processed.",
cart.CartItems.Length),
MessageDate = DateTime.Now,
TargetUserName = cart.UserName
});
cartQueue.DeleteMessage(cqm);
cqm = cartQueue.GetMessage();
}
}
经过对用户通知表中的队列消息的存取操作,位于主页面中的 jQuery Gritter 代码然后会在下一个 15 秒的轮询周期中检测是否存在新消息,然后向用户显示购物车 toast 通知。
总结和后续操作
本文的目的是使开发人员可以抛开其有形的数据中心这条“安全毛毯”,认识到他们可以使用 Windows Azure 执行很多操作,而不仅仅是创建简单的“Hello World”网站。借助 Windows Azure Queues 和 Windows Azure 表存储的强大功能,以及利用这些强大功能在应用程序和其工作者角色之间进行异步消息传送,您可以真正使用 Windows Azure 增强应用程序的引擎了。
为使文章简明易懂,我们将很多代码都保留为原样,没有进行重构。作为熟悉新 Windows Azure Muscle 的练习,请尝试重构本文中的一些代码,以加深对队列的熟练使用,甚至创建一个独立的程序集,其中包含为任何 ASP.NET MVC 网站进行异步消息传送和通知所需的所有代码。
主要是亲自动手实践,创建一些站点并看看您都可以执行哪些操作。本文中的代码位于 Hollywood Hackers 的 CodePlex 站点中。