一個典型的采集服務器體系結構設計
一個基於大量可復用模塊的系統架構
作者:成曉旭
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、 另一個采集子系統:
