zoukankan      html  css  js  c++  java
  • (转)我的架构经验小结(四)-- 实战中演化的三层架构

    在06、07年的时候,我写过一些关于三层架构方面的东西(参见这里),现在看来,觉得有很多实用性的内容需要补充到里面去。我们还是先从架构图看起,然后一一解释,你就会发现相比于两年前,这个架构做了哪些变化和调整。

    一.三层架构图

    二.系统各层次职责

    1.UI(User Interface)层的职责是数据的展现和采集,数据采集的结果通常以Entity object提交给BL层处理。

      Web表示我们常用的B/S应用,WinForm表示我们常用的C/S应用。

    Network层以Socket的方式提供服务给客户端。

    Service层用于将业务或数据资源发布为服务(如WebServices)。

    2.BL(Business Logic)&Platform层的职责是按预定的业务逻辑处理UI层提交的请求,并对核心资源进行管理。

    (1)Business Function 子层负责基本业务功能的实现。

    (2)Business Flow 子层负责将Business Function子层提供的多个基本业务功能组织成一个完整的业务流。

    (3)Platform子层用于统一管理有状态的数据和资源。

    (4)注意:Transaction只能在BusinessFlow/Platform层开启。

    (5)BL最好是没有状态的,而必需的状态管理可以放到Platform中的某些模块/子系统进行。如此可增强系统的可伸缩性。

    (6)Cache子层用于缓存系统常用的数据信息,Cache对于提供系统的并发量和吞吐能力起到至关重要的作用。Cache可以分为以下几类:

    StaticCache

    HotCache

    SyncEntityCache

    RefreshCache

    SubObjectCache

    StaticCache:如果某数据表中的数据是静态的、不会发生变化的,那就非常容易,我们只需要在系统启动的时候,将其加载到内存,以后每次从内存读取数据即可。

    HotCache:如果数据表中的记录非常多,并且修改方面只会有Insert操作,那么我们可以使用HotCache,把那些经常使用的记录缓存在内存中,并且可设定超时机制删除内存中长期不使用的记录。

    SyncEntityCache:如果我们的某个数据表中的数据会发生变化(增删改),但是变化的频率比较低,但是我们的系统对这个表的数据的实时性的敏感度也特别高,那这时候我们就需要用到【实时同步的实体缓存】,这个缓存中的数据在任何时候都与数据表中的数据是完全一致的。

    RefreshCache:如果数据表中的数据会发生变化(增删改),但是变化的频率非常低,而恰巧我们的系统对数据实时性的敏感度也不是特别高,那我们可以使用定时刷新的缓存。

    SubObjectCache:如果某个数据表的修改经常是Insert和Update操作,但是无论如何Update,每条记录有些固定栏位的值都是不会发生变化的,那我们可以把这些不会发生变化的栏位封装在一个【子对象SubObject】中,然后在内存中缓存这些子对象。

    3.DataAccess层的职责是提供全面的资源访问功能支持,并向上层屏蔽资源的来源。

    BEM(Business Entity Manager)子层负责从数据库中存取资源。

    DB Adapter子层负责屏蔽数据库类型的差异。

    ORM子层负责提供对象-关系映射的功能。

    Relation子层提供ORM无法完成的基于关系(Relation)的数据访问功能。

    4.Entity侧层跨越UI/BL&Platform/DataAccess层,在这些层之间传递数据。Entity侧层中包含三类Entity,如下图所示:

    5.DB层可以采用数据库分散放置、读写分离策略来支持超大并发。图中数据库名称,M代表Master(主库),S代表Slave(从库)。

    6.Tools层,架构图中还一个虚线表示的Tools层,之所以用虚线,是因为它并不真的是系统交付的一部分,它并不实现系统的逻辑功能。但它的存在是如此的重要,特别是在我们的开发和测试阶段。它的主要作用有:

    (1)DataMonitor:能将数据库中最重要的信息方便的呈现给工程师,比如重要表和超大表的记录数等。

    (2)DataChecker:直接对数据库中的数据进行完整性、一致性检查。使我们能最及时的发现业务逻辑在数据处理方面的重大失误和错漏。

    (3)DataRepairer:当发现了数据错误并对程序的bug进行修正后,Tools能够对数据进行补充或修复。以使后续开发和测试能立即继续进行。

    三.Aspect

    Aspect贯穿于系统各层,是系统的横切关注点。通常采用AOP技术来对横切关注点进行建模和实现。

    1.Securtiy Aspect:用于对整个系统的Security提供支持。

    2.ErrorHandling Aspect:整个系统采用一致的错误/异常处理方式。

    3.Log Aspect:用于系统异常、日志记录、业务操作记录等。

    (1)通常我们会记录相邻两层的交互接口所引发的所有异常的详细信息,包括方法调用的堆栈帧、调用方法的参数的具体值。(参考这里

    (2)通常我们会跟踪相邻两层的交互接口的每个方法执行所消耗的时间,用于检查系统的性能瓶颈在哪些地方。(参考这里

    (3)通常我们会记录所有数据库访问异常的详细信息,包括sql语句内容、各参数的具体值。(参考这里

    (4)在测试阶段,通常我们会记录所有每个事务访问数据表的顺序,通过对比这些顺序,我们可以发现可能出现死锁的地方,从而加以调整。(DataRabbit内置支持

    (5)另外,一些重要的作业操作我们也会记录到日志。

    四.规则

    1.系统各层次及层内部子层次之间都不得跨层调用。

    2.使用Entity object 在各个层之间传递数据,而不是关系型的DataSet。只有在特殊情况下,才将UI绑定到DataTable,比如返回的结果集没有Entity与之对应的时候。

    3.UI层和BL层禁止出现任何SQL语句。

    4.对于每一个数据库表(Table)都有一个DB Entity class与之对应,针对每一个Entity class都会有一个BEM Class与之对应。

    5.有些跨数据库或跨表的操作(如复杂的联合查询)也需要由相应的BEM Class来提供支持。

    6.对于相对简单的系统,可以考虑将Business Function子层和Business Flow 子层合并为一个。

    五.错误与异常

    异常可以分为系统异常(如网络突然断开)和业务异常(如用户的输入值超出最大范围),业务异常必须被转化为业务执行的结果。

    1. DataAccess层不得向上层隐藏任何异常(该层抛出的异常几乎都是系统异常)。

    2. 要明确区分业务执行的结果和系统异常。比如验证用户的合法性,如果对应的用户ID不存在,不应该抛出异常,而是返回(或通过out参数)一个表示验证结果的枚举值,这属于业务执行的结果。但是,如果在从数据库中提取用户信息时,数据库连接突然断开,则应该抛出系统异常。

    3. 在有些情况下,BL层应根据业务的需要捕获某些系统异常,并将其转化为业务执行的结果。比如,某个业务要求试探指定的数据库是否可连接,这时BL就需要将数据库连接失败的系统异常转换为业务执行的结果。

    4. UI层(包括Service层)除了从调用BL层的API获取的返回值来查看业务的执行结果外,还需要截获所有的系统异常,并将其解释为友好的错误信息呈现给用户。

    5. 当WebService的参数或返回值需要是复杂类型――即架构图中的Service Entity,则Service Entity应该在对应的*.EntranceParaDef.dll中定义。WebService定义的方法中的复杂类型应该使用Xml字符串代替,而Xml字符串和复杂类型对象之间的转换应当在*.Entrance.dll中实现。

          最后,系统架构的思想是重要的,但是架构不能纸上谈兵、不能脱离实践。

          不知您有何补充或建议,请指点一二,呵呵。

    出处:http://www.cnblogs.com/zhuweisky/archive/2009/05/13/1456011.html
  • 相关阅读:
    17.1.2.1 Advantages and Disadvantages of Statement-Based and Row-Based Replication
    17.1.2 Replication Formats
    Setting the Master Configuration on the Slave
    17.1.1.9 Introducing Additional Slaves to an Existing Replication Environment
    17.1.1.8 Setting Up Replication with Existing Data
    17.1.1.7 Setting Up Replication with New Master and Slaves
    17.1.1.6 Creating a Data Snapshot Using Raw Data Files
    列出display的值,并说明它们的作用
    CSS设置DIV居中
    CSS选择符有哪些?哪些属性可以继承?优先级算法如何计算?
  • 原文地址:https://www.cnblogs.com/blsong/p/1851965.html
Copyright © 2011-2022 走看看