www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 電源 > 數(shù)字電源
[導(dǎo)讀]概述:您可以在云中運(yùn)行后臺(tái)進(jìn)程。Kevin Hoffman 和 Nate Dudek 使用購(gòu)物車(chē)示例演示如何構(gòu)建應(yīng)用程序引擎,以及如何使用Azure Storage實(shí)現(xiàn)異步消息傳送和處理。  開(kāi)發(fā)人員容易依賴(lài)其有形的、可感知的基礎(chǔ)結(jié)構(gòu),就像其是“安全毛毯”。他們知道如何使用、如何操作,如果出現(xiàn)問(wèn)題,他們知道問(wèn)題出在哪兒。而這通常會(huì)成為開(kāi)發(fā)人員采用更新的技術(shù)(例如云計(jì)算)的障礙。

心存懷疑的開(kāi)發(fā)人員提出的最大疑問(wèn)之一是他們?nèi)绾卧谠浦欣^續(xù)運(yùn)行后臺(tái)進(jìn)程,即他們的引擎如何繼續(xù)運(yùn)行。本文旨在通過(guò)向您演示如何構(gòu)建應(yīng)用程序引擎以及使用 Windows Azure Storage 實(shí)現(xiàn)異步消息傳送和處理來(lái)為您揭開(kāi)云中缺乏后臺(tái)處理的神秘面紗。

  為了證明開(kāi)發(fā)人員可以拋開(kāi)其有形的基礎(chǔ)結(jié)構(gòu)這條“安全毛毯”并將其應(yīng)用程序引擎置于云中,我們將介紹如何實(shí)現(xiàn)電子商務(wù)應(yīng)用程序的一個(gè)小型子集 Hollywood Hackers,您可以從中購(gòu)買(mǎi)到 Hollywood 用于完全忽略物理法則和過(guò)時(shí)的常識(shí)的所有神奇技術(shù)。

  我們將介紹的兩個(gè)主要方案如下:

  將異步文本消息 (“toasts”) 發(fā)送給使用該應(yīng)用程序的用戶,以通知他們發(fā)生的重要事件(如已提交他們的購(gòu)物車(chē))或在員工之間發(fā)送消息。此方案使用 Windows Azure Queue、Windows Azure Table 和 Windows Azure 工作者角色。

  此方案使用 Windows Azure Queue 和 Windows Azure 工作者角色將購(gòu)物車(chē)提交給執(zhí)行引擎。

  使用隊(duì)列存儲(chǔ)進(jìn)行內(nèi)部應(yīng)用程序消息傳送

  在介紹具體的方案之前,我們需要先介紹一些有關(guān) Windows Azure Queue 的基礎(chǔ)知識(shí)。云中的隊(duì)列與傳統(tǒng)的 .NET 應(yīng)用程序中的隊(duì)列的運(yùn)行方式不太一樣。在處理 AppDomain 中的數(shù)據(jù)時(shí),您知道該數(shù)據(jù)只有一份,它完整地位于單一托管進(jìn)程中。

  而在云中,您的一部分?jǐn)?shù)據(jù)可能在加利福尼亞,而另一部分可能在紐約,并且您可能會(huì)安排一個(gè)工作者角色在德克薩斯州對(duì)該數(shù)據(jù)進(jìn)行處理,而另一工作者角色在北達(dá)科他州進(jìn)行數(shù)據(jù)處理。

很多開(kāi)發(fā)人員在適應(yīng)這種分布式計(jì)算和分布式數(shù)據(jù)時(shí)面臨著一些不熟悉的問(wèn)題,例如對(duì)可能出現(xiàn)的故障進(jìn)行編碼、針對(duì)數(shù)據(jù)提交形成多次重試的概念甚至冪等性的理念。

  只要您不將 Windows Azure Queue 視為進(jìn)程內(nèi)的常規(guī) CLR 隊(duì)列,其工作方式其實(shí)非常簡(jiǎn)單。首先,應(yīng)用程序?qū)⑾蜿?duì)列獲取一些數(shù)量的消息(需要記住,一次不會(huì)超過(guò) 20 條)并提供一個(gè)超時(shí)。此超時(shí)控制對(duì)其他隊(duì)列處理客戶端隱藏這些消息的時(shí)間。當(dāng)應(yīng)用程序成功完成需要對(duì)隊(duì)列消息進(jìn)行的所有處理后,將刪除該消息。

  如果應(yīng)用程序引發(fā)異?;蛱幚黻?duì)列消息失敗,則在超時(shí)期限過(guò)后,其他客戶端可以再次看到該消息。因此,當(dāng)一個(gè)工作者角色處理失敗后,其他工作者角色可以繼續(xù)進(jìn)行處理。向隊(duì)列提交消息非常簡(jiǎn)單:應(yīng)用程序直接或借助客戶端庫(kù)形成適當(dāng)?shù)?HTTP POST 消息,然后提交字符串或字節(jié)數(shù)組。隊(duì)列專(zhuān)門(mén)用于進(jìn)行內(nèi)部應(yīng)用程序消息傳送和非永久存儲(chǔ),因此這些消息占用的空間需要相當(dāng)小。

  如上所述,您可能安排多個(gè)工作者角色都嘗試處理同一消息。雖然隱藏當(dāng)前正在處理的消息的不可見(jiàn)超時(shí)很有幫助,但不能確保萬(wàn)無(wú)一失。要完全避免沖突,您應(yīng)該將您的引擎處理設(shè)計(jì)為冪等。換句話說(shuō),同一隊(duì)列消息應(yīng)該可以由一個(gè)或多個(gè)工作者角色處理多次,而不會(huì)使應(yīng)用程序處于不一致的狀態(tài)。

  理想情況下,您希望工作者角色可以檢測(cè)出是否已完成對(duì)給定消息的處理。在編寫(xiě)工作者角色來(lái)處理隊(duì)列消息時(shí),請(qǐng)牢記您的代碼可能會(huì)嘗試處理已處理過(guò)的消息,盡管這個(gè)可能性微乎其微。

  圖 1 中的代碼段顯示了如何使用隨 Windows Azure SDK 一起提供的 StorageClient 程序集創(chuàng)建消息并將其提交給 Windows Azure Queue。StorageClient 庫(kù)實(shí)際上只是 Windows Azure Storage HTTP 接口周?chē)陌b。

 圖 1 創(chuàng)建消息并將其提交給 Windows Azure Queue

string accountName; 
string accountSharedKey; 
string queueBaseUri; 
string StorageCredentialsAccountAndKey credentials; 
 
if (RoleEnvironment.IsAvailable) 
{ 
// We are running in a cloud - INCLUDING LOCAL! 
 accountName = 
 RoleEnvironment.GetConfigurationSettingValue("AccountName"); 
 accountSharedKey =  
 RoleEnvironment.GetConfigurationSettingValue("AccountSharedKey"); 
 queueBaseUri = RoleEnvironment.GetConfigurationSettingValue 
 ("QueueStorageEndpoint"); 
} 
else 
{ 
 accountName = ConfigurationManager.AppSettings["AccountName"]; 
 accountSharedKey = 
 ConfigurationManager.AppSettings["AccountSharedKey"]; 
 queueBaseUri = 
 ConfigurationManager.AppSettings["QueueStorageEndpoint"]; 
} 
credentials = 
new StorageCredentialsAccountAndKey(accountName, accountSharedKey); 
CloudQueueClient client = 
new CloudQueueClient(queueBaseUri, credentials); 
CloudQueue queue = client.GetQueueReference(queueName); 
CloudQueueMessage m = new CloudQueueMessage( 
 /* string or byte[] representing message to enqueue */); 
Queue.AddMessage(m);

  對(duì)于本文中的其他示例,我們使用了可以簡(jiǎn)化此過(guò)程的一些包裝類(lèi)(位于 Hollywood Hackers 的 CodePlex 站點(diǎn)中,網(wǎng)址為:hollywoodhackers.codeplex.com/SourceControl/ListDownloadableCommits.aspx)。

異步消息傳送 (Toast)

  當(dāng)今,交互式網(wǎng)站不僅是一種時(shí)尚,更是一種需求。用戶已經(jīng)習(xí)慣了完全交互式網(wǎng)站,以致于當(dāng)他們遇到一個(gè)靜態(tài)的非交互式頁(yè)面時(shí)會(huì)認(rèn)為什么地方出問(wèn)題了。考慮到這一點(diǎn),我們希望可以在我們的用戶使用這樣的站點(diǎn)時(shí)向他們發(fā)送通知。

  為此,我們將利用 Windows Azure Queue 和 Windows Azure Table 存儲(chǔ)機(jī)制構(gòu)建一個(gè)消息傳遞框架??蛻舳藢⑹褂门c jQuery Gritter 插件結(jié)合的 jQuery 在用戶的瀏覽器中將通知顯示為一個(gè) toast,類(lèi)似于當(dāng)您收到新的 Outlook 電子郵件、即時(shí)消息或警報(bào)聲時(shí)在 Windows 系統(tǒng)托盤(pán)上方淡出的消息。

  當(dāng)需要向某個(gè)用戶發(fā)送通知時(shí),該用戶將被插入到隊(duì)列中。因?yàn)楣ぷ髡呓巧?fù)責(zé)處理隊(duì)列中的每個(gè)項(xiàng)目,所以該角色將動(dòng)態(tài)確定如何處理每個(gè)項(xiàng)目。在本例中,引擎只需要執(zhí)行一個(gè)操作,但在復(fù)雜的 CRM 網(wǎng)站或支持站點(diǎn)中,要執(zhí)行的操作可能不計(jì)其數(shù)。

  工作者角色在隊(duì)列中遇到用戶通知時(shí),會(huì)將該通知存儲(chǔ)在表存儲(chǔ)中并將其從隊(duì)列中刪除。這樣,消息可以保留很長(zhǎng)時(shí)間并等待用戶登錄進(jìn)行處理。隊(duì)列存儲(chǔ)中的消息的最大保存期限比較短,不會(huì)超過(guò)幾天。當(dāng)用戶訪問(wèn)網(wǎng)站時(shí),我們的 jQuery 腳本將異步獲取表中的所有消息,并通過(guò)在控制器上調(diào)用可返回 JavaScript Object Notation (JSON) 的方法在瀏覽器中以常見(jiàn)的形式顯示這些消息。

  盡管隊(duì)列只處理字符串或字節(jié)數(shù)組,但我們可以通過(guò)將任何類(lèi)型的結(jié)構(gòu)化數(shù)據(jù)序列化為二進(jìn)制文件來(lái)將其存儲(chǔ)在隊(duì)列中,然后在我們需要使用時(shí)再將其轉(zhuǎn)換回來(lái)。這成為將強(qiáng)類(lèi)型化的對(duì)象傳遞到隊(duì)列中的出色技術(shù)。我們會(huì)將此技術(shù)構(gòu)建到我們的隊(duì)列消息的基類(lèi)中。然后,我們的系統(tǒng)消息類(lèi)可以包含我們的數(shù)據(jù),而且可以將整個(gè)對(duì)象提交到隊(duì)列中并根據(jù)需要進(jìn)行利用(請(qǐng)參見(jiàn)圖 2)。

 圖 2 在隊(duì)列中存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)

namespace HollywoodHackers.Storage.Queue 
{ 
  [Serializable] 
  public class QueueMessageBase 
  { 
    public byte[] ToBinary() 
    { 
      BinaryFormatter bf = new BinaryFormatter(); 
      MemoryStream ms = new MemoryStream(); 
      ms.Position = 0; 
      bf.Serialize(ms, this); 
      byte[] output = ms.GetBuffer(); 
      ms.Close(); 
      return output; 
    } 
    public static T FromMessage<T>(CloudQueueMessage m) 
    { 
      byte[] buffer = m.AsBytes(); 
      MemoryStream ms = new MemoryStream(buffer); 
      ms.Position = 0; 
      BinaryFormatter bf = new BinaryFormatter(); 
      return (T)bf.Deserialize(ms); 
    } 
  } 
  [Serializable] 
  public class ToastQueueMessage : QueueMessageBase 
  { 
  public ToastQueueMessage() 
      : base() 
    { 
    } 
    public string TargetUserName { get; set; }     
    public string MessageText { get; set; } 
    public string Title { get; set; } 
    public DateTime CreatedOn { get; set; }    
  }

 請(qǐng)記住,要使用 BinaryFormatter 類(lèi),需要以完全信任模式(可以通過(guò)服務(wù)配置文件啟用此模式)運(yùn)行 Windows Azure 工作者角色。 [!--empirenews.page--]
 現(xiàn)在,我們需要一個(gè)簡(jiǎn)單的包裝來(lái)與我們的隊(duì)列交互。從本質(zhì)上說(shuō),我們需要能夠?qū)⑾⒉迦腙?duì)列,獲取任何掛起的消息并清除該隊(duì)列(請(qǐng)參見(jiàn)圖 3)。

  圖 3 用于與隊(duì)列交互的包裝

namespace HollywoodHackers.Storage.Queue 
{ 
  public class StdQueue<T> : 
  StorageBase where T : QueueMessageBase, new() 
  { 
    protected CloudQueue queue; 
    protected CloudQueueClient client; 
 
    public StdQueue(string queueName) 
    { 
      client = new CloudQueueClient 
      (StorageBase.QueueBaseUri, StorageBase.Credentials); 
      queue = client.GetQueueReference(queueName); 
      queue.CreateIfNotExist(); 
    } 
    public void AddMessage(T message) 
    { 
      CloudQueueMessage msg = 
      new CloudQueueMessage(message.ToBinary()); 
      queue.AddMessage(msg); 
    } 
    public void DeleteMessage(CloudQueueMessage msg) 
    { 
      queue.DeleteMessage(msg); 
    } 
    public CloudQueueMessage GetMessage() 
    { 
      return queue.GetMessage(TimeSpan.FromSeconds(60)); 
    } 
  } 
  public class ToastQueue : StdQueue<ToastQueueMessage> 
  { 
    public ToastQueue() 
      : base("toasts") 
    { 
    } 
  } 
}

我們還需要為表存儲(chǔ)設(shè)置一個(gè)包裝,以便在用戶登錄到站點(diǎn)之前可以存儲(chǔ)用戶通知。可以使用 PartitionKey(行集合的標(biāo)識(shí)符)和 RowKey(可唯一標(biāo)識(shí)特定分區(qū)中的每個(gè)單獨(dú)行)組織表數(shù)據(jù)。選擇 PartitionKey 和 RowKey 使用的數(shù)據(jù)是在使用表存儲(chǔ)時(shí)所做的最重要的設(shè)計(jì)決策之一。

  這些特點(diǎn)允許跨存儲(chǔ)節(jié)點(diǎn)進(jìn)行負(fù)載平衡,并在應(yīng)用程序中提供內(nèi)置的可伸縮性選項(xiàng)。不考慮數(shù)據(jù)的數(shù)據(jù)中心關(guān)聯(lián)性,使用同一分區(qū)鍵的表存儲(chǔ)中的行將保留在相同的物理數(shù)據(jù)存儲(chǔ)中。因?yàn)獒槍?duì)每個(gè)用戶存儲(chǔ)對(duì)應(yīng)的消息,所以分區(qū)鍵將是 UserName,而 RowKey 則成為標(biāo)識(shí)每行的 GUID(請(qǐng)參見(jiàn)圖 4)。

  圖 4 表存儲(chǔ)的包裝

namespace HollywoodHackers.Storage.Repositories 
{ 
  public class UserTextNotificationRepository : StorageBase 
  { 
    public const string EntitySetName = 
    "UserTextNotifications"; 
    CloudTableClient tableClient; 
    UserTextNotificationContext notificationContext; 
    public UserTextNotificationRepository() 
      : base() 
    { 
      tableClient = new CloudTableClient 
      (StorageBase.TableBaseUri, StorageBase.Credentials); 
      notificationContext = new UserTextNotificationContext 
      (StorageBase.TableBaseUri,StorageBase.Credentials); 
 
      tableClient.CreateTableIfNotExist(EntitySetName); 
    } 
    public UserTextNotification[] 
    GetNotificationsForUser(string userName) 
    { 
      var q = from notification in 
          notificationContext.UserNotifications 
          where notification.TargetUserName == 
          userName select notification; 
      return q.ToArray(); 
    } 
    public void AddNotification 
    (UserTextNotification notification) 
    { 
      notification.RowKey = Guid.NewGuid().ToString(); 
      notificationContext.AddObject 
      (EntitySetName, notification); 
      notificationContext.SaveChanges(); 
    } 
  } 
}

因?yàn)槲覀兊拇鎯?chǔ)機(jī)制已經(jīng)確定,所以我們需要一個(gè)工作者角色作為引擎;以便在我們的電子商務(wù)站點(diǎn)的后臺(tái)處理消息。為此,我們定義了一個(gè)從 Microsoft.ServiceHosting.ServiceRuntime.RoleEntryPoint 類(lèi)繼承的類(lèi),并將其與云服務(wù)項(xiàng)目中的工作者角色關(guān)聯(lián)(請(qǐng)參見(jiàn)圖 5)。

  圖 5 作為引擎的工作者角色

public class WorkerRole : RoleEntryPoint 
{ 
  ShoppingCartQueue cartQueue; 
  ToastQueue toastQueue; 
  UserTextNotificationRepository toastRepository; 
 
  public override void Run() 
  { 
    // This is a sample worker implementation. 
    //Replace with your logic. 
    Trace.WriteLine("WorkerRole1 entry point called", 
    "Information"); 
    toastRepository = new UserTextNotificationRepository(); 
    InitQueue(); 
    while (true) 
    { 
      Thread.Sleep(10000); 
      Trace.WriteLine("Working", "Information"); 
 
      ProcessNewTextNotifications(); 
      ProcessShoppingCarts(); 
    } 
  } 
  private void InitQueue() 
  { 
    cartQueue = new ShoppingCartQueue(); 
    toastQueue = new ToastQueue(); 
  } 
  private void ProcessNewTextNotifications() 
  { 
    CloudQueueMessage cqm = toastQueue.GetMessage(); 
    while (cqm != null) 
    { 
      ToastQueueMessage message = 
      QueueMessageBase.FromMessage<ToastQueueMessage>(cqm); 
 
      toastRepository.AddNotification(new 
      UserTextNotification() 
      { 
        MessageText = message.MessageText, 
        MessageDate = DateTime.Now, 
        TargetUserName = message.TargetUserName, 
        Title = message.Title 
      }); 
      toastQueue.DeleteMessage(cqm); 
      cqm = toastQueue.GetMessage(); 
    } 
  } 
  private void ProcessShoppingCarts() 
  { 
    // We will add this later in the article! 
  } 
  public override bool OnStart() 
  { 
    // Set the maximum number of concurrent connections 
    ServicePointManager.DefaultConnectionLimit = 12; 
 
    DiagnosticMonitor.Start("DiagnosticsConnectionString"); 
    // For information on handling configuration changes 
    // see the MSDN topic at 
    //http://go.microsoft.com/fwlink/?LinkId=166357. 
    RoleEnvironment.Changing += RoleEnvironmentChanging; 
    return base.OnStart(); 
  } 
  private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e) 
  { 
    // If a configuration setting is changing 
    if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)) 
    { 
      // Set e.Cancel to true to restart this role instance 
      e.Cancel = true; 
    } 
  } 
}

讓我們看一下工作者角色代碼。在初始化和設(shè)置所需的隊(duì)列和表存儲(chǔ)之后,此代碼將進(jìn)入一個(gè)循環(huán)。每 10 秒鐘,它就會(huì)處理一次隊(duì)列中的消息。每次我們通過(guò)處理循環(huán)時(shí)都將獲取隊(duì)列中的消息,直到最終返回 null,這表示隊(duì)列為空。

  您從隊(duì)列中看到的消息永遠(yuǎn)不會(huì)超過(guò) 20 個(gè),如果不信,您可以反復(fù)嘗試來(lái)驗(yàn)證一下。對(duì)隊(duì)列進(jìn)行的任何處理都有時(shí)間限制,必須在該時(shí)間范圍內(nèi)對(duì)每個(gè)隊(duì)列消息執(zhí)行有意義的操作,否則隊(duì)列消息將被視為超時(shí),并在隊(duì)列中顯示備份,以便可以由其他工作者來(lái)處理此消息。每個(gè)消息都會(huì)作為用戶通知添加到表存儲(chǔ)中。關(guān)于工作者角色需要記住的重要一點(diǎn)是:一旦入口點(diǎn)方法完成,工作者角色也就結(jié)束了。這就是您需要在一個(gè)循環(huán)中保持邏輯運(yùn)行的原因。

  從客戶端的角度來(lái)說(shuō),我們需要能夠以 JSON 形式返回消息,以便 jQuery 可以異步輪詢(xún)并顯示新的用戶通知。為此,我們會(huì)將一些代碼添加到消息控制器中,以便可以訪問(wèn)這些通知(請(qǐng)參見(jiàn)圖 6)。

  圖 6 以 JSON 形式返回消息

public JsonResult GetMessages() 
{ 
   if (User.Identity.IsAuthenticated) 
   { 
UserTextNotification[] userToasts = 
    toastRepository.GetNotifications(User.Identity.Name); 
object[] data = 
(from UserTextNotification toast in userToasts 
      select new { title = toast.Title ?? "Notification", 
 text = toast.MessageText }).ToArray(); 
      return Json(data, JsonRequestBehavior.AllowGet); 
   } 
   else 
     return Json(null); 
}

 在 Visual Studio 2010 beta 2 下的 ASP.NET MVC 2(我們用于撰寫(xiě)本文的環(huán)境)中,如果沒(méi)有 JsonRequestBehavior.AllowGet 選項(xiàng),您無(wú)法將 JSON 數(shù)據(jù)返回到 jQuery 或其他客戶端。在 ASP.NET MVC 1 中,不需要此選項(xiàng)。現(xiàn)在,我們可以編寫(xiě) JavaScript,它每 15 秒將調(diào)用一次 GetMessages 方法并將以 toast 形式消息顯示通知(請(qǐng)參見(jiàn)圖 7)。 [!--empirenews.page--]
 圖 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) 
});

  提交和處理購(gòu)物車(chē)

  在我們的示例應(yīng)用程序中,我們希望使用隊(duì)列存儲(chǔ)執(zhí)行的另一個(gè)關(guān)鍵方案是提交購(gòu)物車(chē)。Hollywood Hackers 有一個(gè)第三方履行系統(tǒng)(Hollywood Hackers 無(wú)法在其空間有限的倉(cāng)庫(kù)中保留所有小工具),所以引擎需要對(duì)購(gòu)物車(chē)進(jìn)行一些處理。一旦引擎完成其處理,它會(huì)向用戶通知隊(duì)列提交一個(gè)消息,告知用戶已經(jīng)對(duì)購(gòu)物車(chē)進(jìn)行了處理(或者出現(xiàn)了問(wèn)題)。如果處理購(gòu)物車(chē)時(shí)用戶處于在線狀態(tài),該用戶將收到系統(tǒng)彈出的一個(gè) toast 消息。如果用戶不在線,則會(huì)在其下次登錄到該站點(diǎn)時(shí)收到該彈出消息,如圖 8 所示。

圖 8 示例用戶通知

  查看原圖(大圖)

  我們首先需要的是一些包裝類(lèi),使我們可以與購(gòu)物車(chē)隊(duì)列交互。這些包裝非常簡(jiǎn)單,如果要查看它們的源代碼,可以在 CodePlex 站點(diǎn)上查看。

  與標(biāo)準(zhǔn) CRUD(創(chuàng)建、讀取、更新、刪除)存儲(chǔ)庫(kù)不同的是,隊(duì)列中的讀取操作不是單純的讀取操作。請(qǐng)記住,只要獲取隊(duì)列中的消息,必須在有限的時(shí)間內(nèi)處理該消息,操作失敗或刪除消息都會(huì)顯示處理完成。這種模式不能順利地轉(zhuǎn)換到存儲(chǔ)庫(kù)模式,所以我們已經(jīng)不再借助包裝類(lèi)執(zhí)行此操作。

  現(xiàn)在,我們已經(jīng)擁有了要與購(gòu)物車(chē)隊(duì)列交互的代碼,我們可以將一些代碼放在購(gòu)物車(chē)控制器中,以便將購(gòu)物車(chē)內(nèi)容提交到隊(duì)列中(請(qǐng)參見(jiàn)圖 9)。

  圖 9 向隊(duì)列提交購(gòu)物車(chē)

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(); 
  }

在實(shí)際情況下,您可能會(huì)從進(jìn)程外狀態(tài)(例如會(huì)話存儲(chǔ)、緩存或窗體發(fā)布)獲得購(gòu)物車(chē)。為了簡(jiǎn)化本文代碼,我們僅僅構(gòu)建了購(gòu)物車(chē)的內(nèi)容。

  最后,購(gòu)物車(chē)內(nèi)容已處于隊(duì)列中,我們可以修改工作者角色,以便它可以定期檢查隊(duì)列中掛起的購(gòu)物車(chē)。它每次會(huì)從隊(duì)列中選擇一個(gè)購(gòu)物車(chē),用整整一分鐘對(duì)該購(gòu)物車(chē)進(jìn)行處理,然后向用戶通知隊(duì)列提交一個(gè)消息,告知用戶已經(jīng)對(duì)該購(gòu)物車(chē)進(jìn)行了處理(請(qǐng)參見(jiàn)圖 10)。

  圖 10 檢查隊(duì)列中掛起的購(gòu)物車(chē)

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(); 
  } 
}

  經(jīng)過(guò)對(duì)用戶通知表中的隊(duì)列消息的存取操作,位于主頁(yè)面中的 jQuery Gritter 代碼然后會(huì)在下一個(gè) 15 秒的輪詢(xún)周期中檢測(cè)是否存在新消息,然后向用戶顯示購(gòu)物車(chē) toast 通知。


  總結(jié)和后續(xù)操作

  本文的目的是使開(kāi)發(fā)人員可以拋開(kāi)其有形的數(shù)據(jù)中心這條“安全毛毯”,認(rèn)識(shí)到他們可以使用 Windows Azure 執(zhí)行很多操作,而不僅僅是創(chuàng)建簡(jiǎn)單的“Hello World”網(wǎng)站。借助 Windows Azure Queues 和 Windows Azure 表存儲(chǔ)的強(qiáng)大功能,以及利用這些強(qiáng)大功能在應(yīng)用程序和其工作者角色之間進(jìn)行異步消息傳送,您可以真正使用 Windows Azure 增強(qiáng)應(yīng)用程序的引擎了。

  為使文章簡(jiǎn)明易懂,我們將很多代碼都保留為原樣,沒(méi)有進(jìn)行重構(gòu)。作為熟悉新 Windows Azure Muscle 的練習(xí),請(qǐng)嘗試重構(gòu)本文中的一些代碼,以加深對(duì)隊(duì)列的熟練使用,甚至創(chuàng)建一個(gè)獨(dú)立的程序集,其中包含為任何 ASP.NET MVC 網(wǎng)站進(jìn)行異步消息傳送和通知所需的所有代碼。

  主要是親自動(dòng)手實(shí)踐,創(chuàng)建一些站點(diǎn)并看看您都可以執(zhí)行哪些操作。本文中的代碼位于 Hollywood Hackers 的 CodePlex 站點(diǎn)中。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱(chēng),數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱(chēng)"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉