petshop4.0 详解

问题描述

PetShop数据访问层之消息处理在进行系统设计时,除了对安全、事务等问题给与足够的重视外,性能也是一个不可避免的问题所在,尤其是一个B/S结构的软件系统,必须充分地考虑访问量、数据流量、服务器负荷的问题。解决性能的瓶颈,除了对硬件系统进行升级外,软件设计的合理性尤为重要。在前面我曾提到,分层式结构设计可能会在一定程度上影响数据访问的性能,然而与它给设计人员带来的好处相比,几乎可以忽略。要提供整个系统的性能,还可以从数据库的优化着手,例如连接池的使用、建立索引、优化查询策略等等,例如在PetShop中就利用了数据库的Cache,对于数据量较大的订单数据,则利用分库的方式为其单独建立了Order和Inventory数据库。而在软件设计上,比较有用的方式是利用多线程与异步处理方式。在PetShop4.0中,使用了MicrosoftMessagingQueue(MSMQ)技术来完成异步处理,利用消息队列临时存放要插入的数据,使得数据访问因为不需要访问数据库从而提供了访问性能,至于队列中的数据,则等待系统空闲的时候再进行处理,将其最终插入到数据库中。PetShop4.0中的消息处理,主要分为如下几部分:消息接口IMessaging、消息工厂MessagingFactory、MSMQ实现MSMQMessaging以及数据后台处理应用程序OrderProcessor。从模块化分上,PetShop自始自终地履行了“面向接口设计”的原则,将消息处理的接口与实现分开,并通过工厂模式封装消息实现对象的创建,以达到松散耦合的目的。由于在PetShop中仅对订单的处理使用了异步处理方式,因此在消息接口IMessaging中,仅定义了一个IOrder接口,其类图如下:在对消息接口的实现中,考虑到未来的扩展中会有其他的数据对象会使用MSMQ,因此定义了一个Queue的基类,实现消息Receive和Send的基本操作:publicvirtualobjectReceive(){     try{         using(Messagemessage=queue.Receive(timeout,transactionType))            returnmessage;     }     catch(MessageQueueExceptionmqex){         if(mqex.MessageQueueErrorCode==MessageQueueErrorCode.IOTimeout)            thrownewTimeoutException();               throw;     }}publicvirtualvoidSend(objectmsg){     queue.Send(msg,transactionType);}其中queue对象是System.Messaging.MessageQueue类型,作为存放数据的队列。MSMQ队列是一个可持久的队列,因此不必担心用户不间断地下订单会导致订单数据的丢失。在PetShopQueue设置了timeout值,OrderProcessor会根据timeout值定期扫描队列中的订单数据。MSMQMessaging模块中,Order对象实现了IMessaging模块中定义的接口IOrder,同时它还继承了基类PetShopQueue,其定义如下:publicclassorder:PetShopQueue,PetShop.IMessaging.IOrder方法的实现代码如下:   publicneworderInfoReceive()   {       //ThismethodinvolvesindistributedtransactionandneedAutomaticTransactiontype       base.transactionType=MessageQueueTransactionType.Automatic;       return(OrderInfo)((Message)base.Receive()).Body;   }   publicorderInfoReceive(inttimeout)   {       base.timeout=TimeSpan.FromSeconds(Convert.ToDouble(timeout));       returnReceive();   }   publicvoidSend(OrderInfoorderMessage)   {       //ThismethoddoesnotinvolveindistributedtransactionandoptimizesperformanceusingSingletype       base.transactionType=MessageQueueTransactionType.Single;       base.Send(orderMessage);   }所以,最后的类图应该如下:注意在Order类的Receive()方法中,是用new关键字而不是override关键字来重写其父类PetShopQueue的Receive()虚方法。因此,如果是实例化如下的对象,将会调用PetShopQueue的Receive()方法,而不是子类Order的Receive()方法:PetShopQueuequeue=neworder();queue.Receive();从设计上来看,由于PetShop采用“面向接口设计”的原则,如果我们要创建Order对象,应该采用如下的方式:IOrderorder=neworder();order.Receive();考虑到IOrder的实现有可能的变化,PetShop仍然利用了工厂模式,将IOrder对象的创建用专门的工厂模块进行了封装:在类QueueAccess中,通过CreateOrder()方法利用反射技术创建正确的IOrder类型对象:   publicstaticPetShop.IMessaging.IOrderCreateOrder()   {       stringclassName=path+".Order";       returnPetShop.IMessaging.IOrder)Assembly.Load(path).CreateInstance(className);   }path的值通过配置文件获取:privatestaticreadonlystringpath=ConfigurationManager.AppSettings["OrderMessaging"];而配置文件中,OrderMessaging的值设置如下:<addkey="OrderMessaging"value="PetShop.MSMQMessaging"/>之所以利用工厂模式来负责对象的创建,是便于在业务层中对其调用,例如在BLL模块中OrderAsynchronous类:publicclassorderAsynchronous:IOrderStrategy{          privatestaticreadonlyPetShop.IMessaging.IOrderasynchOrder=PetShop.MessagingFactory.QueueAccess.CreateOrder();   publicvoidInsert(PetShop.Model.OrderInfoorder){       asynchOrder.Send(order);   }}一旦IOrder接口的实现发生变化,这种实现方式就可以使得客户仅需要修改配置文件,而不需要修改代码,如此就可以避免程序集的重新编译和部署,使得系统能够灵活应对需求的改变。例如定义一个实现IOrder接口的SpecialOrder,则可以新增一个模块,如PetShop.SpecialMSMQMessaging,而类名则仍然为Order,那么此时我们仅需要修改配置文件中OrderMessaging的值即可:<addkey="OrderMessaging"value="PetShop.SpecialMSMQMessaging"/>OrderProcessor是一个控制台应用程序,不过可以根据需求将其设计为WindowsService。它的目的就是接收消息队列中的订单数据,然后将其插入到Order和Inventory数据库中。它利用了多线程技术,以达到提高系统性能的目的。在OrderProcessor应用程序中,主函数Main用于控制线程,而核心的执行任务则由方法ProcessOrders()实现:   privatestaticvoidProcessOrders()   {       //thetransactiontimeoutshouldbelongenoughtohandleallofordersinthebatch       TimeSpantsTimeout=TimeSpan.FromSeconds(Convert.ToDouble(transactionTimeout*batchSize));       orderorder=neworder();       while(true)       {           //queuetimeoutvariables           TimeSpandatetimeStarting=newTimeSpan(DateTime.Now.Ticks);           doubleelapsedTime=0;           intprocessedItems=0;           ArrayListqueueOrders=newArrayList();           using(TransactionScopets=newTransactionScope(TransactionScopeOption.Required,tsTimeout))           {               //Receivetheordersfromthequeue               for(intj=0;j<batchSize;j++)               {                   try                   {                       //onlyreceivemorequeuedordersifthereisenoughtime                       if((elapsedTime+queueTimeout+transactionTimeout)<tsTimeout.TotalSeconds)                       {                           queueOrders.Add(order.ReceiveFromQueue(queueTimeout));                       }                       else                       {                           j=batchSize;  //exitloop                       }                       //updateelapsedtime                       elapsedTime=newTimeSpan(DateTime.Now.Ticks).TotalSeconds-datetimeStarting.TotalSeconds;

解决方案

解决方案二:
}catch(TimeoutException){//exitloopbecausenomoremessagesarewaitingj=batchSize;}}//processthequeuedordersfor(intk=0;k<queueOrders.Count;k++){order.Insert((OrderInfo)queueOrders[k]);processedItems++;totalOrdersProcessed++;}//batchcompleteorMSMQreceivetimedoutts.Complete();}Console.WriteLine("(ThreadId"+Thread.CurrentThread.ManagedThreadId+")batchfinished,"+processedItems+"items,in"+elapsedTime.ToString()+"seconds.");}}首先,它会通过PetShop.BLL.Order类的公共方法ReceiveFromQueue()来获取消息队列中的订单数据,并将其放入到一个ArrayList对象中,然而再调用PetShop.BLL.Order类的Insert方法将其插入到Order和Inventory数据库中。在PetShop.BLL.Order类中,并不是直接执行插入订单的操作,而是调用了IOrderStrategy接口的Insert()方法:publicvoidInsert(OrderInfoorder){//CallcreditcardprocesorProcessCreditCard(order);//Inserttheorder(a)synchrounouslybasedonconfigurationorderInsertStrategy.Insert(order);}在这里,运用了一个策略模式,类图如下所示:在PetShop.BLL.Order类中,仍然利用配置文件来动态创建IOrderStategy对象:privatestaticreadonlyPetShop.IBLLStrategy.IOrderStrategyorderInsertStrategy=LoadInsertStrategy();privatestaticPetShop.IBLLStrategy.IOrderStrategyLoadInsertStrategy(){//Lookupwhichstrategytousefromconfigfilestringpath=ConfigurationManager.AppSettings["OrderStrategyAssembly"];stringclassName=ConfigurationManager.AppSettings["OrderStrategyClass"];//Usingtheevidencegivenintheconfigfileloadtheappropriateassemblyandclassreturn(PetShop.IBLLStrategy.IOrderStrategy)Assembly.Load(path).CreateInstance(className);}由于OrderProcessor是一个单独的应用程序,因此它使用的配置文件与PetShop不同,是存放在应用程序的App.config文件中,在该文件中,对IOrderStategy的配置为:<addkey="OrderStrategyAssembly"value="PetShop.BLL"/><addkey="OrderStrategyClass"value="PetShop.BLL.OrderSynchronous"/>因此,以异步方式插入订单的流程如下图所示:MicrosoftMessagingQueue(MSMQ)技术除用于异步处理以外,它主要还是一种分布式处理技术。分布式处理中,一个重要的技术要素就是有关消息的处理,而在System.Messaging命名空间中,已经提供了Message类,可以用于承载消息的传递,前提上消息的发送方与接收方在数据定义上应有统一的接口规范。MSMQ在分布式处理的运用,在我参与的项目中已经有了实现。在为一个汽车制造商开发一个大型系统时,分销商Dealer作为.Net客户端,需要将数据传递到管理中心,并且该数据将被Oracle的EBS(E-BusinessSystem)使用。由于分销商管理系统(DMS)采用的是C/S结构,数据库为SQLServer,而汽车制造商管理中心的EBS数据库为Oracle。这里就涉及到两个系统之间数据的传递。实现架构如下:首先Dealer的数据通过MSMQ传递到MSMQServer,此时可以将数据插入到SQLServer数据库中,同时利用FTP将数据传送到专门的文件服务器上。然后利用IBM的EAI技术(企业应用集成,EnterpriseApplicationItegration)定期将文件服务器中的文件,利用接口规范写入到EAI数据库服务器中,并最终写道EBS的Oracle数据库中。上述架构是一个典型的分布式处理结构,而技术实现的核心就是MSMQ和EAI。由于我们已经定义了统一的接口规范,在通过消息队列形成文件后,此时的数据就已经与平台无关了,使得在.Net平台下的分销商管理系统能够与Oracle的EBS集成起来,完成数据的处理。
解决方案三:
sf
解决方案四:
路过~~学习~~
解决方案五:
mark
解决方案六:
没细看,MARK
解决方案七:
引用3楼lsq667的回复:

路过~~学习~~

解决方案八:
引用6楼stning的回复:

引用3楼lsq667的回复:路过~~学习~~

解决方案九:
引用7楼shiling_02404的回复:

引用6楼stning的回复:引用3楼lsq667的回复:路过~~学习~~

解决方案十:
mark
解决方案十一:
mark
解决方案十二:
mark
解决方案十三:
up
解决方案十四:
学习
解决方案十五:
非常好!支持!
解决方案:
mark
解决方案:
学习!
解决方案:
路过~~学习
解决方案:
该回复于2008-03-19 08:34:58被版主删除
解决方案:
good
解决方案:
路过。
解决方案:
OK
解决方案:
学习
解决方案:
谢谢,收藏了!
解决方案:
mark
解决方案:
支持
解决方案:
up
解决方案:
谢谢了学习了
解决方案:
mark

时间: 2024-12-12 06:28:39

petshop4.0 详解的相关文章

国内首款完全由国人自主研发的开源云平台 BDC3.0 详解

问题描述 国内首款完全由国人自主研发的开源云平台BDC3.0详解 解决方案 解决方案二: 解决方案三:不管如何,顶一下解决方案四:看看呢....

Android安装apk文件并适配Android 7.0详解

Android安装apk文件并适配Android 7.0详解 首先在AndroidManifest.xml文件,activity同级节点注册provider: <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.file_provider" android:exported="false"

0.0.0.0 详解

RFC: 0.0.0.0/8 - Addresses in this block refer to source hosts on "this"network. Address 0.0.0.0/32 may be used as a source address for thishost on this network; other addresses within 0.0.0.0/8 may be used torefer to specified hosts on this net

Windows下的PHP5.0详解_php技巧

PHP5包括以下一些重要的特征:  ·支持新的对象模型和许多新特点的Zend引擎. ·完全重新编写了XML支持,扩展性能围绕着优秀的libxml2库(http://www.xmlsoft.org/). ·新的SimpleXML扩展,PHP对象轻松访问操作. ·全新的内建SOAP扩展,支持Web服务的交换. ·增加命名为MySQLi的了MySQL的扩展,支持MySQL4.1及以后版本的功能. ·绑定SQLite数据库. ·极大地改进流的设计,包括通过流操作底层的socket 首先,点这里下载PHP

IBM Lotus Quickr V8.0详解

新一代的内容协作平台 Lotus Quickr 8.0 于 6 月 26 日在全球发布,Lotus Quickr 的诞生将对企业协同办公产生深远的影响.本文将为您更加深入的揭示 Lotus Quickr 的主要功能与特点. [编辑注:本文中所展示的截图和特性是 IBM Lotus Quickr services for Portal版本,而 Lotus Quickr services for Domino 版本的特性和 UI 界面会稍有不同.] 本文将从以下几个方面来介绍 Quickr 的特性:

iOS中 蓝牙2.0详解/ios蓝牙设备详解

版权声明:本文为博主原创文章,未经博主允许不得转载. 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 整体布局如下:     程序结构如右图: 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 ========================================================================== 指定根视图: [objc] view plain copy RootViewContr

iOS中 蓝牙2.0详解/ios蓝牙设备详解 韩俊强的博客

每日更新关注:http://weibo.com/hanjunqiang  新浪微博 整体布局如下:     程序结构如右图: 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 ========================================================================== 指定根视图: RootViewController * rootVC = [[RootViewController alloc] init]

Android xUtils更新到3.0后的基本使用规则详解_Android

 说实话,对于xUtils,是我最近才用到的开发框架(也是刚接触),对于其功能不得不说,简化了很多的开发步骤,可以说是非常好的开发工具,但是其最近更新到3.0也没有解决加载自定义ImageView报错的问题. xUtils简介 xUtils 包含了很多实用的android工具. xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响... xUitls 最低兼容android 2.2 (api level 8) 我总是喜欢

Laravel 5.0 发布 新版本特性详解

 这篇文章主要介绍了Laravel 5.0 发布 新版本特性详解,本文讲解了目录结构.Contracts.路由缓存.路由中间.控制器方法注入.认证脚手架等新特性,需要的朋友可以参考下     译注: 期待 Laravel 5.0 已经很久很久了, 之前跳票说要到今年一月份发布. 从一月份就一直在刷新官网和博客, 始终没有更新的消息, 前几天终于看到官网文档切换到了 5.0 版. 新版本带来了众多令人激动的新特性, 尤其是定时任务队列和表单请求两个特性, 光看一下更新说明中的简单介绍都忍不住要上手