zoukankan      html  css  js  c++  java
  • 一个典型的采集服务器体系结构设计

    一个典型的采集服务器体系结构设计

    一个基于大量可复用模块的系统架构

    作者:成晓旭

    http://blog.csdn.net/cxxsoft

    (声明:版权保留,欢迎转载、请保证文章完整性)

    1、   整个系统简介

    假设系统是一个常见的监控、数据采集系统的实例缩影:系统的最底层是硬件采集设备,硬件设备完成整个系统与外界环境或者设备的交互;上层的软件系统完成与自己硬件设备的交互,并且对采集的数据进行分析、处理、存储、展现。

     


    2、   问题

               在我工作的软件项目中,类似的应用存在于多个软件系统中,虽然这些系统在子系统设计及职责划分方面也如上图一般进行了明确的分层及模块化,但在核心的“通信采集子系统”的设计及实现上存在诸多通病,导致整个子系统的可理解性、可维护性、可测试性、对需求变动的适应性极差。集中表现在:

               A、整个系统被设计成一个“非常庞大”的“业务调度控制类”:此类中包括几乎所有的通信业务管理、通信中转、界面显示驱动、显示数据生成等。

               B、在通信方式实现类(比如:串口通信类、语音卡控制类、TCP/IP通信类)中完成所有业务处理功能:通信任务管理、下行命令队列管理、通信数据的收发、通信协议的解析、业务数据的分析甚至存储,甚至有些系统中还包括显示数据的生成及界面显示驱动。

               C、对于多任务并发,多个设备上、下行同时通信的管理非常复杂:在通信处理类中引入非常、非常多的数组来处理多任务并发,增加非常多的控制标志来标识记录具体某个设备当前所处的通信状态。由于没有进行单独的业务抽象,当系统测试或上线运行之后,系统中实际的运行状态管理和运行标志判断,对调试人员或者系统维护人员来说,简单是一场噩梦!“整个系统就跟森林似的!”,已经是很多同事不约而同的感慨。

               D、对于需求变化的适应性非常差:如果通信方式变了,对不起,你必须重新实现通信处理类;当然,所有的通信控制逻辑、协议解析、数据分析及存储、并行控制及管理、队列管理等功能你也必须重新开发了。如果通信协议变了、数据分析逻辑变了,你必须小心翼翼、如履薄冰地在“通信处理类”的那成千上万行代码里找寻找你关心的蛛丝马迹。

               E、几乎没有可复用性了:那个家伙熬更守夜花两周研究的语音卡控制代码,你想尊重一下那位大侠的劳动成果,直接拿过来用几乎是不可能的,因为那稀少的语音卡代码,早已淹没在茫茫的业务处理代码中了。如果新签订的合同需要更换新的通信采集方式,那成千上万行业务控制代码你想将就用用也是难上加难的。

    3、   采集服务器设计

               采集服务器是整个系统的核心,实现与硬件终端的通信、下行命令的执行、上行数据的接收、协议解析,并且完成业务数据的分析、存储以及显示驱动。它既是系统的通信枢纽,也是业务核心。

               下图是本人2004年设计的一个采集子系统体系结构的缩影。

     


    A、  通信采集子系统设计简介

    本系统设计主要参考了大量的实时系统设计模式,并分析、总结了以前多个系统的设计与实现的经验与教训。

    采集子系统的“外部系统接口类”,设计成Façade模式:在整个系统中,其它子系统需要执行什么控制命令、或者需要得到什么数据,只需通过“外部系统接口类”向采集子系统发出简单的命令请求,具体的实现细节不用操心,采集子系统完成命令之后,将结果再通过“外部系统接口类”反馈给命令发起者。甚至命令的处理逻辑已经完全不同了,发起者仍然可以一如既往地执行相同的命令,得到其期望的反馈信息。

    采集子系统借鉴“微内核”的实时设计模式:核心的通信、控制处理逻辑被严格封装在“采集控制器”中,“采集控制器”设计为一个抽象的“采集业务状态机”,也是一个自管理的可运行单元(比如:实现为一个线程、或者独立的服务进程),对外界实现一个通用的类似于计算机CPU一样的通信处理器,通过对其外围增加“命令队列”、“采集业务类”、“通信适配器”等“外围器件”实现一个针对具体功能应用的“主板”。

    建立整个子系统的业务对象关联的是一个Mediator模式:用以最大可能地解耦各个功能组件,彻底解决各个功能组件之间直接相互引用(因为这些组件之间存在必然的逻辑关联)的问题。每个功能组件都只需引用Mediator,也只需与Mediator类交互。比如:外界接口类通过Mediator与命令队列交互,采集控制器的数据只能通过Mediator来存储到数据库中,从此不再引用复杂的数据库相关类及代码,采集到的数据也通过Mediator与显示控制器交互,不再与界面组件紧密耦合。Mediator是采集子系统的业务调度中心和请求中转站,但是它从不自己具体实现任何功能。

    在数据处理方面,引入“命令队列”作为数据缓存机制:“命令队列”是子系统“任务信息”的分界点,其上是任务的请求者,其下是任务的执行者,是典型的Command模式应用。除了缓存下行命令之外,“命令队列”主要目的是降低“业务调度中心”与“采集控制器”的耦合度,并且解决“采集控制器”与“业务调度中心”之间“异步执行”的问题。

    B、  基本出发点就是可复用性:

    a)          通信采集方式(如:串口通信类、语音卡控制类、TCP/IP通信类)代码可复用

    b)         命令队列管理代码可复用

    c)          标准界面通用组件库

    d)         通信协议代码可复用(本系统内通用)

    e)          通信采集业务代码可复用(本系统内通用)

    f)          业务DAO类代码可复用(本系统内通用)

    g)          外部系统接口类(本系统内通用)

    C、 应用的设计模式或者沿用的设计模式原理:

    a)          整个系统采用MVC的设计模式:业务数据、显示控制及界面显示严格分层,单独实现。业务数据通过下层模块产生,通用“业务调度核心”这个中介与“界面接口定制类”这个控制器交互;控制器“界面接口定制类”可以根据不同的显示需要进行定制,与不同的界面组件交互,可满足不同的显示需求;在界面显示层,引用了其它项目中实现的“标准界面通用组件库”中的部分源码。

    b)         业务调度中心采用Mediator模式。

    c)          采集控制器采用“微内核”的实时设计模式。

    d)         命令队列采用Command模式:以强制分离命令的发起者与命令的执行者。

    e)          多通信方式、多通信协议的支持方面都采用Adapter模式:解耦“采集控制器”与“通信方式”,“采集控制器”与“通信协议”,并方便更换或者增加的通信方式、通信协议。

    f)          “采集控制器”采用State模式:通过抽象业务状态机,可以灵活地实现不同采集控制需求。并且,如果采集方式类是语音卡之类的设备时,采集类里面也往往采集“状态机”模式来管理这类自身以状态方式驱动的通信设备。

    g)          “采集控制器”内部,对多协议的自动处理采用Chain Of Responsibility:将多个协议组件组织成一条“职责链”,实现对当前通信协议的自动识别、自动解析功能。(当时的系统没有实现)

    h)         “采集控制器”内部,考虑并发和性能,采用“通道”的实时设计模式:以尽可能地提升系统并发能力、提高系统吞吐能力(当时的系统没有实现)。

    i)           “采集控制器”内部,采用“轮巡”和“中断”的实时设计模式:为检测通信链路是否可用,在通信空闲时,系统要求与硬件终端进行定期“通信握手”,当“采集控制器”检测以“命令队列”或者“硬件终端”的任务请求时采用“中断”方式立即响应上、下行命令。

    D、 主要模块简介

    a)          DB访问引擎:通用的数据库访问引擎代码,实现对各类不同的数据库访问代码;

    b)         业务DAO类库:本系统的数据库业务逻辑代码库;

    c)          业务调度核心类:是采集子系统的业务调度中心和业务请求中转站。外部系统的命令请求通过“接口子系统”转入到“业务调度核心类”,“业务调度核心类”将命令请求存入命令队列中;“采集控制器”采集到数据之后,回调到“业务调度核心类”,之后,“业务调度核心类”调用“业务DAO类库”相关方法完成数据存储,并通过“界面接口类”完成数据显示;再通过“外部接口类”向其它系统反馈实时运行信息。

    d)         外部系统接口类:采集子系统与外部系统的信息接口模块,通过定制的协议和通信接口与外部系统提供信息交互;比如:接收外部系统的命令请求、向外部系统反馈命令执行结果。

    e)          命令队列:下行任务信息缓存类。“业务调度核心类”向其中增加命令请求;“采集控制器”自动检测是否有新命令请求,当检测到后立即“中断”通信握手,执行请求,执行成功之后,从队列中删除该命令。

    f)          采集控制类:检测命令队列,管理、协调其下的“采集业务”、“通信方式”、“通信协议”等模块,完成所有的通信及数据采集功能。

    g)          采集业务类:封装当前系统的具体采集业务对象,为通用的“采集控制类”定制具体的采集任务。

    h)         通信适配器:采集方式的Adapter。

    i)           协议适配类:通信协议的Adapter。

    j)           采集方式类:封装具体的串口、TCP/IP、语音卡等通信采集类,实现具体的通信方式控制及通用的数据收发接口。

    k)         通信协议类:封装系统中软件与硬件的通信协议。

    4、   需求变化的易适应性实例

             采用此体系结构的软件在2005年现场试点中,果真遇到为其它厂商提供软件接口的需求变更,并要求快速实现,最终,需求的变更三次,此结构基本上都能较快满足。具体的示例如下(分割后实际用到的模块包围在红线以内):

    A、  只提供包括通信方式控制和硬件协议的接口模块(以DLL方式提供):

            

            

    B、  包括命令队列、接口子系统和采集控制器的接口模块(以EXE独立进程方式提供):

    图错了......

    C、  提供与数据库无关的功能完整的接口模块(以EXE独立进程方式提供):

     

            

             为满足此需求,将数据库访问、数据DAO及数据加载、存储等代码强制移植到另一个子系统中,并且将“业务调度核心类”强制拆分成上、下两部分,当时和同事PP在现场也没有花多少时间就搞定了,工作量大大少于我们自己的预计。


    5、   体系结构应用实例

             在本人以后的项目开发中,先后两次沿用了此体系结构,并较快速地完成了两个新的应用子系统。简略示例如下:

    A、  语音告警通知子系统:

     


    B、  另一个采集子系统:


     

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/CXXSoft/archive/2006/09/18/1236331.aspx

  • 相关阅读:
    java struts2入门学习实例--用户注册
    java struts2入门学习实例--将客户端IP地址和访问方式输出到浏览器
    struts2基本配置详解2
    struts2基本配置详解
    使用maven+eclipse搭建最简单的struts2的HelloWorld
    2013年总结
    linux shell 脚本攻略学习20--awk命令入门详解
    linux shell 脚本攻略学习19--sed命令详解
    linux shell 脚本攻略学习18--grep命令详解
    linux shell 脚本攻略学习17--正则表达式入门
  • 原文地址:https://www.cnblogs.com/qlp1982/p/2035341.html
Copyright © 2011-2022 走看看