pet的结构单元_三层架构

pet的结构单元_三层架构PetShop4架构设计分析(三) petshop4.0详解之三(PetShop数据访问层之消息处理)三、PetShop数据访问层之消息处理在进行系统设计时,除了对安全、事务等问题给与足够的重视外,性能也是一个不可避免的问题所在,尤其是一个B/S结构的软件系统,必须充分地考虑访问量、数据流量、服务器负荷的问题。解决性能的瓶颈,除了对硬件系统进行升级外,软件设计的合理性尤为重要。在前

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

PetShop4架构设计分析(三) 

petshop4.0 详解之三(PetShop数据访问层之消息处理)

三、PetShop数据访问层之消息处理

在进行系统设计时,除了对安全、事务等问题给与足够的重视外,性能也是一个不可避免的问题所在,尤其是一个B/S结构的软件系统,必须充分地考虑访问量、数据流量、服务器负荷的问题。解决性能的瓶颈,除了对硬件系统进行升级外,软件设计的合理性尤为重要。

在前面我曾提到,分层式结构设计可能会在一定程度上影响数据访问的性能,然而与它给设计人员带来的好处相比,几乎可以忽略。要提供整个系统的性能,还可以从数据库的优化着手,例如连接池的使用、建立索引、优化查询策略等等,例如在PetShop中就利用了数据库的Cache,对于数据量较大的订单数据,则利用分库的方式为其单独建立了Order和Inventory数据库。而在软件设计上,比较有用的方式是利用多线程与异步处理方式。

在PetShop4.0中,使用了Microsoft Messaging Queue(MSMQ)技术来完成异步处理,利用消息队列临时存放要插入的数据,使得数据访问因为不需要访问数据库从而提供了访问性能,至于队列中的数据,则等待系统空闲的时候再进行处理,将其最终插入到数据库中。

PetShop4.0中的消息处理,主要分为如下几部分:消息接口IMessaging、消息工厂MessagingFactory、MSMQ实现MSMQMessaging以及数据后台处理应用程序OrderProcessor。

从模块化分上,PetShop自始自终地履行了“面向接口设计”的原则,将消息处理的接口与实现分开,并通过工厂模式封装消息实现对象的创建,以达到松散耦合的目的。

由于在PetShop中仅对订单的处理使用了异步处理方式,因此在消息接口IMessaging中,仅定义了一个IOrder接口,其类图如下:

 
ps01.gif

在对消息接口的实现中,考虑到未来的扩展中会有其他的数据对象会使用MSMQ,因此定义了一个Queue的基类,实现消息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对象是System.Messaging.MessageQueue类型,作为存放数据的队列。MSMQ队列是一个可持久的队列,因此不必担心用户不间断地下订单会导致订单数据的丢失。在PetShopQueue设置了timeout值,OrderProcessor会根据timeout值定期扫描队列中的订单数据。

MSMQMessaging模块中,Order对象实现了IMessaging模块中定义的接口IOrder,同时它还继承了基类PetShopQueue,其定义如下:

public class order:PetShopQueue, PetShop.IMessaging.IOrder

方法的实现代码如下:

    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);
    }
所以,最后的类图应该如下:
 ps02.gif
注意在Order类的Receive()方法中,是用new关键字而不是override关键字来重写其父类PetShopQueue的Receive()虚方法。因此,如果是实例化如下的对象,将会调用PetShopQueue的Receive()方法,而不是子类Order的Receive()方法:
PetShopQueue queue = new order();
queue.Receive();
从设计上来看,由于PetShop采用“面向接口设计”的原则,如果我们要创建Order对象,应该采用如下的方式:
IOrder order = new order();
order.Receive();
考虑到IOrder的实现有可能的变化,PetShop仍然利用了工厂模式,将IOrder对象的创建用专门的工厂模块进行了封装:
 ps03.gif
在类QueueAccess中,通过CreateOrder()方法利用反射技术创建正确的IOrder类型对象:
    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的值设置如下:
<add key=”OrderMessaging” value=”PetShop.MSMQMessaging”/>
之所以利用工厂模式来负责对象的创建,是便于在业务层中对其调用,例如在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接口的实现发生变化,这种实现方式就可以使得客户仅需要修改配置文件,而不需要修改代码,如此就可以避免程序集的重新编译和部署,使得系统能够灵活应对需求的改变。例如定义一个实现IOrder接口的SpecialOrder,则可以新增一个模块,如PetShop.SpecialMSMQMessaging,而类名则仍然为Order,那么此时我们仅需要修改配置文件中OrderMessaging的值即可:
<add key=”OrderMessaging” value=”PetShop.SpecialMSMQMessaging”/>
OrderProcessor是一个控制台应用程序,不过可以根据需求将其设计为Windows Service。它的目的就是接收消息队列中的订单数据,然后将其插入到Order和Inventory数据库中。它利用了多线程技术,以达到提高系统性能的目的。
在OrderProcessor应用程序中,主函数Main用于控制线程,而核心的执行任务则由方法ProcessOrders()实现:
    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.”);
        }
    }
首先,它会通过PetShop.BLL.Order类的公共方法ReceiveFromQueue()来获取消息队列中的订单数据,并将其放入到一个ArrayList对象中,然而再调用PetShop.BLL.Order类的Insert方法将其插入到Order和Inventory数据库中。
在PetShop.BLL.Order类中,并不是直接执行插入订单的操作,而是调用了IOrderStrategy接口的Insert()方法:
public void Insert(OrderInfo order)
{

    // Call credit card procesor
    ProcessCreditCard(order);

    // Insert the order (a)synchrounously based on configuration
    orderInsertStrategy.Insert(order);
}
在这里,运用了一个策略模式,类图如下所示:
 ps05.gif
在PetShop.BLL.Order类中,仍然利用配置文件来动态创建IOrderStategy对象:
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是一个单独的应用程序,因此它使用的配置文件与PetShop不同,是存放在应用程序的App.config文件中,在该文件中,对IOrderStategy的配置为:
<add key=”OrderStrategyAssembly” value=”PetShop.BLL” />
<add key=”OrderStrategyClass” value=”PetShop.BLL.OrderSynchronous” />
因此,以异步方式插入订单的流程如下图所示:
 ps06.gif
Microsoft Messaging Queue(MSMQ)技术除用于异步处理以外,它主要还是一种分布式处理技术。分布式处理中,一个重要的技术要素就是有关消息的处理,而在System.Messaging命名空间中,已经提供了Message类,可以用于承载消息的传递,前提上消息的发送方与接收方在数据定义上应有统一的接口规范。
MSMQ在分布式处理的运用,在我参与的项目中已经有了实现。在为一个汽车制造商开发一个大型系统时,分销商Dealer作为.Net客户端,需要将数据传递到管理中心,并且该数据将被Oracle的EBS(E-Business System)使用。由于分销商管理系统(DMS)采用的是C/S结构,数据库为SQL Server,而汽车制造商管理中心的EBS数据库为Oracle。这里就涉及到两个系统之间数据的传递。
实现架构如下:
ps07.gif
     首先Dealer的数据通过MSMQ传递到MSMQ Server,此时可以将数据插入到SQL Server数据库中,同时利用FTP将数据传送到专门的文件服务器上。然后利用IBM的EAI技术(企业应用集成,Enterprise Application Itegration)定期将文件服务器中的文件,利用接口规范写入到EAI数据库服务器中,并最终写道EBS的Oracle数据库中。
上述架构是一个典型的分布式处理结构,而技术实现的核心就是MSMQ和EAI。由于我们已经定义了统一的接口规范,在通过消息队列形成文件后,此时的数据就已经与平台无关了,使得在.Net平台下的分销商管理系统能够与Oracle的EBS集成起来,完成数据的处理。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/181204.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • msm8953 uart配置

    msm8953 uart配置参考链接:MSM8937-MSM8953UART配置调试指南uart驱动是使用内核驱动,无需自己编写,一般只需修改设备树。一、修改设备树设备树的配置有三部分:1.msm8953.dtsi中添加code blsp2_uart2:serial@7af0000{ compatible=”qcom,msm-lsuart-v14″; reg=<0x7af00000x…

  • 耶鲁大学博弈论24讲笔记_耶鲁大学博弈论公开课讲义

    耶鲁大学博弈论24讲笔记_耶鲁大学博弈论公开课讲义耶鲁大学博弈论(GameTheory)笔记2-学会换位思考

  • linux history 历史命令行查询和使用

    linux history 历史命令行查询和使用history命令:用于显示历史记录和执行过的指令命令,可以使用符号!执行指定序号的历史命令。例如,要执行第2个历史命令,则输入!2。history命令:是被保存在内存中的,当退出或者登录shell时,会自动保存或读取。默认是不显示命令的执行时间,命令的执行时间,history已经记录,只是没有显示。注:如想查询某个用户在系统上执行了什么命令,可以使用root用户身份登录系统,检查Hom…

  • 树莓派自动连接蓝牙_树莓派能搜到wifi但是连不上

    树莓派自动连接蓝牙_树莓派能搜到wifi但是连不上将USB无线网卡插入树莓派任一USB接口,插上网线,接通电源;在个人电脑上通过ssh连接树莓派,默认帐号是pi,默认密码是raspberry(如何通过ssh连接树莓派,请自行网上查找,当然如果树莓派已

  • 挖矿程序处理[通俗易懂]

    挖矿程序处理[通俗易懂]记一次工作中遇到得挖矿程序处理首先需要减少中毒得几率,就是不要把ssh密码设得太简单,然后ssl端口号改改,改加的访问次数限制加上,常用的sql,代码管理工具等等port也都改掉,管理员权限账户不要多建挖矿程序特点,cpu占用率贼高300,kill不尽,会出现一些自己不曾安装过的程序,库等挖矿程序一般是杀死不净的,需要找到程序路径,以及自启动的脚本ls/proc/进程号/exe-la删掉相关程序but你会发现,它在其他地方又新建了脚本…

  • Excel宏教程 (宏的介绍与基本使用)

    Excel宏教程 (宏的介绍与基本使用)Excel宏教程(宏的介绍与基本使用)Microsoftexcel是一款功能非常强大的电子表格软件。它可以轻松地完成数据的各类数学运算,并用各种二维或三维图形形象地表示出来,从而大大简化了数据的处理工作。但若仅利用excel的常用功能来处理较复杂的数据,可能仍需进行大量的人工操作。但excel的强大远远超过人们的想象–宏的引入使其具有了无限的扩展性,因而可以很好地解决复杂

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号