主頁 > 知識(shí)庫 > 《解剖PetShop》之三:PetShop數(shù)據(jù)訪問層之消息處理

《解剖PetShop》之三:PetShop數(shù)據(jù)訪問層之消息處理

熱門標(biāo)簽:臨沂智能電話機(jī)器人加盟 地圖標(biāo)注軟件免費(fèi)下載 400電話辦理怎么樣 聯(lián)通官網(wǎng)400電話辦理 西寧呼叫中心外呼系統(tǒng)線路商 百應(yīng)電話機(jī)器人外呼系統(tǒng) 外呼電話機(jī)器人成本 蘇州如何辦理400電話 網(wǎng)絡(luò)電話外呼系統(tǒng)上海

三、PetShop數(shù)據(jù)訪問層之消息處理

  在進(jìn)行系統(tǒng)設(shè)計(jì)時(shí),除了對(duì)安全、事務(wù)等問題給與足夠的重視外,性能也是一個(gè)不可避免的問題所在,尤其是一個(gè)B/S結(jié)構(gòu)的軟件系統(tǒng),必須充分地考慮訪問量、數(shù)據(jù)流量、服務(wù)器負(fù)荷的問題。解決性能的瓶頸,除了對(duì)硬件系統(tǒng)進(jìn)行升級(jí)外,軟件設(shè)計(jì)的合理性尤為重要。

  在前面我曾提到,分層式結(jié)構(gòu)設(shè)計(jì)可能會(huì)在一定程度上影響數(shù)據(jù)訪問的性能,然而與它給設(shè)計(jì)人員帶來的好處相比,幾乎可以忽略。要提供整個(gè)系統(tǒng)的性能,還可以從數(shù)據(jù)庫的優(yōu)化著手,例如連接池的使用、建立索引、優(yōu)化查詢策略等等,例如在PetShop中就利用了數(shù)據(jù)庫的Cache,對(duì)于數(shù)據(jù)量較大的訂單數(shù)據(jù),則利用分庫的方式為其單獨(dú)建立了Order和Inventory數(shù)據(jù)庫。而在軟件設(shè)計(jì)上,比較有用的方式是利用多線程與異步處理方式。

  在PetShop4.0中,使用了Microsoft Messaging Queue(MSMQ)技術(shù)來完成異步處理,利用消息隊(duì)列臨時(shí)存放要插入的數(shù)據(jù),使得數(shù)據(jù)訪問因?yàn)椴恍枰L問數(shù)據(jù)庫從而提供了訪問性能,至于隊(duì)列中的數(shù)據(jù),則等待系統(tǒng)空閑的時(shí)候再進(jìn)行處理,將其最終插入到數(shù)據(jù)庫中。

  PetShop4.0中的消息處理,主要分為如下幾部分:消息接口IMessaging、消息工廠MessagingFactory、MSMQ實(shí)現(xiàn)MSMQMessaging以及數(shù)據(jù)后臺(tái)處理應(yīng)用程序OrderProcessor。

  從模塊化分上,PetShop自始自終地履行了“面向接口設(shè)計(jì)”的原則,將消息處理的接口與實(shí)現(xiàn)分開,并通過工廠模式封裝消息實(shí)現(xiàn)對(duì)象的創(chuàng)建,以達(dá)到松散耦合的目的。

  由于在PetShop中僅對(duì)訂單的處理使用了異步處理方式,因此在消息接口IMessaging中,僅定義了一個(gè)IOrder接口,其類圖如下:

  在對(duì)消息接口的實(shí)現(xiàn)中,考慮到未來的擴(kuò)展中會(huì)有其他的數(shù)據(jù)對(duì)象會(huì)使用MSMQ,因此定義了一個(gè)Queue的基類,實(shí)現(xiàn)消息Receive和Send的基本操作:

public virtual object Receive()
{
 try
 {
  using (Message message = queue.Receive(timeout, transactionType))
   return message;
 }
 catch (MessageQueueException mqex)
 {
  if (mqex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
   throw new TimeoutException();
   throw;
 }
}
public virtual void Send(object msg)
{
  queue.Send(msg, transactionType);
}


  其中queue對(duì)象是System.Messaging.MessageQueue類型,作為存放數(shù)據(jù)的隊(duì)列。MSMQ隊(duì)列是一個(gè)可持久的隊(duì)列,因此不必?fù)?dān)心用戶不間斷地下訂單會(huì)導(dǎo)致訂單數(shù)據(jù)的丟失。在PetShopQueue設(shè)置了timeout值,OrderProcessor會(huì)根據(jù)timeout值定期掃描隊(duì)列中的訂單數(shù)據(jù)。

  MSMQMessaging模塊中,Order對(duì)象實(shí)現(xiàn)了IMessaging模塊中定義的接口IOrder,同時(shí)它還繼承了基類PetShopQueue,其定義如下:

public class Order:PetShopQueue, PetShop.IMessaging.IOrder
 
  方法的實(shí)現(xiàn)代碼如下:
public new OrderInfo Receive()
{
 // This method involves in distributed transaction and need Automatic Transaction type
 base.transactionType = MessageQueueTransactionType.Automatic;
 return (OrderInfo)((Message)base.Receive()).Body;
}

public OrderInfo Receive(int timeout)
{
 base.timeout = TimeSpan.FromSeconds(Convert.ToDouble(timeout));
 return Receive();
}

public void Send(OrderInfo orderMessage)
{
 // This method does not involve in distributed transaction and optimizes performance using Single type
 base.transactionType = MessageQueueTransactionType.Single;
 base.Send(orderMessage);
}

所以,最后的類圖應(yīng)該如下:

注意在Order類的Receive()方法中,是用new關(guān)鍵字而不是override關(guān)鍵字來重寫其父類PetShopQueue的Receive()虛方法。因此,如果是實(shí)例化如下的對(duì)象,將會(huì)調(diào)用PetShopQueue的Receive()方法,而不是子類Order的Receive()方法:

PetShopQueue queue = new Order();
queue.Receive();

從設(shè)計(jì)上來看,由于PetShop采用“面向接口設(shè)計(jì)”的原則,如果我們要?jiǎng)?chuàng)建Order對(duì)象,應(yīng)該采用如下的方式:

IOrder order = new Order();
order.Receive();

考慮到IOrder的實(shí)現(xiàn)有可能的變化,PetShop仍然利用了工廠模式,將IOrder對(duì)象的創(chuàng)建用專門的工廠模塊進(jìn)行了封裝:

在類QueueAccess中,通過CreateOrder()方法利用反射技術(shù)創(chuàng)建正確的IOrder類型對(duì)象:

public static PetShop.IMessaging.IOrder CreateOrder()
{
 string className = path + ".Order";
 return PetShop.IMessaging.IOrder)Assembly.Load(path).CreateInstance(className);
}

path的值通過配置文件獲取:

private static readonly string path = ConfigurationManager.AppSettings["OrderMessaging"];

而配置文件中,OrderMessaging的值設(shè)置如下:

add key="OrderMessaging" value="PetShop.MSMQMessaging"/>

之所以利用工廠模式來負(fù)責(zé)對(duì)象的創(chuàng)建,是便于在業(yè)務(wù)層中對(duì)其調(diào)用,例如在BLL模塊中OrderAsynchronous類:

public class OrderAsynchronous : IOrderStrategy
{  
 private static readonly PetShop.IMessaging.IOrder asynchOrder = PetShop.MessagingFactory.QueueAccess.CreateOrder();
 public void Insert(PetShop.Model.OrderInfo order)
 {
  asynchOrder.Send(order);
 }
}

  一旦IOrder接口的實(shí)現(xiàn)發(fā)生變化,這種實(shí)現(xiàn)方式就可以使得客戶僅需要修改配置文件,而不需要修改代碼,如此就可以避免程序集的重新編譯和部署,使得系統(tǒng)能夠靈活應(yīng)對(duì)需求的改變。例如定義一個(gè)實(shí)現(xiàn)IOrder接口的SpecialOrder,則可以新增一個(gè)模塊,如PetShop.SpecialMSMQMessaging,而類名則仍然為Order,那么此時(shí)我們僅需要修改配置文件中OrderMessaging的值即可:

add key="OrderMessaging" value="PetShop.SpecialMSMQMessaging"/>

OrderProcessor是一個(gè)控制臺(tái)應(yīng)用程序,不過可以根據(jù)需求將其設(shè)計(jì)為Windows Service。它的目的就是接收消息隊(duì)列中的訂單數(shù)據(jù),然后將其插入到Order和Inventory數(shù)據(jù)庫中。它利用了多線程技術(shù),以達(dá)到提高系統(tǒng)性能的目的。
  在OrderProcessor應(yīng)用程序中,主函數(shù)Main用于控制線程,而核心的執(zhí)行任務(wù)則由方法ProcessOrders()實(shí)現(xiàn):

private static void ProcessOrders()
{
 // the transaction timeout should be long enough to handle all of orders in the batch
 TimeSpan tsTimeout = TimeSpan.FromSeconds(Convert.ToDouble(transactionTimeout * batchSize));

 Order order = new Order();
 while (true)
 {
  // queue timeout variables
  TimeSpan datetimeStarting = new TimeSpan(DateTime.Now.Ticks);
  double elapsedTime = 0;

  int processedItems = 0;

  ArrayList queueOrders = new ArrayList();

  using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, tsTimeout))
  {
   // Receive the orders from the queue
   for (int j = 0; j  batchSize; j++)
   {
    try
    {
     //only receive more queued orders if there is enough time
     if ((elapsedTime + queueTimeout + transactionTimeout)  tsTimeout.TotalSeconds)
     {
      queueOrders.Add(order.ReceiveFromQueue(queueTimeout));
     }
     else
     {
      j = batchSize; // exit loop
     }

     //update elapsed time
     elapsedTime = new TimeSpan(DateTime.Now.Ticks).TotalSeconds - datetimeStarting.TotalSeconds;
    }
    catch (TimeoutException)
    {
     //exit loop because no more messages are waiting
     j = batchSize;
    }
   }
   //process the queued orders
   for (int k = 0; k  queueOrders.Count; k++)
   {
    order.Insert((OrderInfo)queueOrders[k]);
    processedItems++;
    totalOrdersProcessed++;
   }

   //batch complete or MSMQ receive timed out
   ts.Complete();
  }

  Console.WriteLine("(Thread Id " + Thread.CurrentThread.ManagedThreadId + ") batch finished, " + processedItems + " items, in " + elapsedTime.ToString() + " seconds.");
 }
}

  首先,它會(huì)通過PetShop.BLL.Order類的公共方法ReceiveFromQueue()來獲取消息隊(duì)列中的訂單數(shù)據(jù),并將其放入到一個(gè)ArrayList對(duì)象中,然而再調(diào)用PetShop.BLL.Order類的Insert方法將其插入到Order和Inventory數(shù)據(jù)庫中。

在PetShop.BLL.Order類中,并不是直接執(zhí)行插入訂單的操作,而是調(diào)用了IOrderStrategy接口的Insert()方法:

public void Insert(OrderInfo order)
{
 // Call credit card procesor
 ProcessCreditCard(order);

 // Insert the order (a)synchrounously based on configuration
 orderInsertStrategy.Insert(order);
}

在這里,運(yùn)用了一個(gè)策略模式,類圖如下所示:

在PetShop.BLL.Order類中,仍然利用配置文件來動(dòng)態(tài)創(chuàng)建IOrderStategy對(duì)象:

private static readonly PetShop.IBLLStrategy.IOrderStrategy orderInsertStrategy = LoadInsertStrategy();
private static PetShop.IBLLStrategy.IOrderStrategy LoadInsertStrategy()
{
 // Look up which strategy to use from config file
 string path = ConfigurationManager.AppSettings["OrderStrategyAssembly"];
 string className = ConfigurationManager.AppSettings["OrderStrategyClass"];

 // Using the evidence given in the config file load the appropriate assembly and class
 return (PetShop.IBLLStrategy.IOrderStrategy)Assembly.Load(path).CreateInstance(className);
}

由于OrderProcessor是一個(gè)單獨(dú)的應(yīng)用程序,因此它使用的配置文件與PetShop不同,是存放在應(yīng)用程序的App.config文件中,在該文件中,對(duì)IOrderStategy的配置為:

add key="OrderStrategyAssembly" value="PetShop.BLL" />
add key="OrderStrategyClass" value="PetShop.BLL.OrderSynchronous" />

因此,以異步方式插入訂單的流程如下圖所示:

  Microsoft Messaging Queue(MSMQ)技術(shù)除用于異步處理以外,它主要還是一種分布式處理技術(shù)。分布式處理中,一個(gè)重要的技術(shù)要素就是有關(guān)消息的處理,而在System.Messaging命名空間中,已經(jīng)提供了Message類,可以用于承載消息的傳遞,前提上消息的發(fā)送方與接收方在數(shù)據(jù)定義上應(yīng)有統(tǒng)一的接口規(guī)范。

  MSMQ在分布式處理的運(yùn)用,在我參與的項(xiàng)目中已經(jīng)有了實(shí)現(xiàn)。在為一個(gè)汽車制造商開發(fā)一個(gè)大型系統(tǒng)時(shí),分銷商Dealer作為.Net客戶端,需要將數(shù)據(jù)傳遞到管理中心,并且該數(shù)據(jù)將被Oracle的EBS(E-Business System)使用。由于分銷商管理系統(tǒng)(DMS)采用的是C/S結(jié)構(gòu),數(shù)據(jù)庫為SQL Server,而汽車制造商管理中心的EBS數(shù)據(jù)庫為Oracle。這里就涉及到兩個(gè)系統(tǒng)之間數(shù)據(jù)的傳遞。
實(shí)現(xiàn)架構(gòu)如下:

  首先Dealer的數(shù)據(jù)通過MSMQ傳遞到MSMQ Server,此時(shí)可以將數(shù)據(jù)插入到SQL Server數(shù)據(jù)庫中,同時(shí)利用FTP將數(shù)據(jù)傳送到專門的文件服務(wù)器上。然后利用IBM的EAI技術(shù)(企業(yè)應(yīng)用集成,Enterprise Application Itegration)定期將文件服務(wù)器中的文件,利用接口規(guī)范寫入到EAI數(shù)據(jù)庫服務(wù)器中,并最終寫道EBS的Oracle數(shù)據(jù)庫中。
上述架構(gòu)是一個(gè)典型的分布式處理結(jié)構(gòu),而技術(shù)實(shí)現(xiàn)的核心就是MSMQ和EAI。由于我們已經(jīng)定義了統(tǒng)一的接口規(guī)范,在通過消息隊(duì)列形成文件后,此時(shí)的數(shù)據(jù)就已經(jīng)與平臺(tái)無關(guān)了,使得在.Net平臺(tái)下的分銷商管理系統(tǒng)能夠與Oracle的EBS集成起來,完成數(shù)據(jù)的處理。

以上就是PetShop數(shù)據(jù)訪問層消息處理部分的全部內(nèi)容,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

您可能感興趣的文章:
  • 學(xué)會(huì)sql數(shù)據(jù)庫關(guān)系圖(Petshop)
  • 《解剖PetShop》之一:PetShop的系統(tǒng)架構(gòu)設(shè)計(jì)
  • 《解剖PetShop》之二:PetShop數(shù)據(jù)訪問層數(shù)之據(jù)庫訪問設(shè)計(jì)
  • 《解剖PetShop》之四:PetShop之ASP.NET緩存
  • 《解剖PetShop》之五:PetShop之業(yè)務(wù)邏輯層設(shè)計(jì)
  • 《解剖PetShop》之六:PetShop之表示層設(shè)計(jì)

標(biāo)簽:中衛(wèi) 臨夏 海西 清遠(yuǎn) 慶陽 甘肅 聊城

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《《解剖PetShop》之三:PetShop數(shù)據(jù)訪問層之消息處理》,本文關(guān)鍵詞  解剖PetShop,之三,PetShop,數(shù)據(jù),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《《解剖PetShop》之三:PetShop數(shù)據(jù)訪問層之消息處理》相關(guān)的同類信息!
  • 本頁收集關(guān)于《解剖PetShop》之三:PetShop數(shù)據(jù)訪問層之消息處理的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章