徐 丹,艾文凱
(南京南瑞繼保電氣有限公司 研究院數(shù)據(jù)平臺部,南京 211101)
隨著電力系統(tǒng)高實時要求應用的發(fā)展,時間序列數(shù)據(jù)庫在電力系統(tǒng)中的應用越來越廣泛,廣域測量系統(tǒng)、變電站監(jiān)控、調度、直流、穩(wěn)控等多個電力自動化系統(tǒng)中都能見到身影,用于滿足存儲海量、高頻數(shù)據(jù)的需求.時間序列數(shù)據(jù)庫主要用于處理秒級、毫秒級高頻數(shù)據(jù),每個存儲周期(毫秒或是秒)會產生一批數(shù)據(jù),因此數(shù)據(jù)量極大,對網絡流量和網絡中間件的讀寫性能要求極高,通用架構的網絡中間件很難滿足時間序列數(shù)據(jù)庫的特別要求,需要定制開發(fā)適用于時間序列數(shù)據(jù)庫的網絡中間件,針對報文、網絡和存儲特點進行全面優(yōu)化.
RPC的基本通信模型是基于Client/Server進程間相互通信模型的一種同步通信形式;它對Client提供了遠程服務的過程抽象,其底層消息傳遞操作對Client是透明的.在 RPC 中,Client即是請求服務的調用者(Caller),而Server則是執(zhí)行Client的請求而被調用的程序(Callee)[1,2].
這種形式的網絡中間件以DCOM與COBRA為代表,但無論哪種標準與實現(xiàn),均由以下部份組成.
(1)實際完成服務和功能的遠程對象,負責實際完成系統(tǒng)服務,接受遠程請求.
(2)訪問客戶端代理,負責從客戶端接受請求,并將請求轉換為遠程調用發(fā)送到服務端.
(3)對象請求代理 ORB,提供一個通信框架,透明的在異構分布式計算環(huán)境中傳遞對象請求,負責定位對象實現(xiàn),并將請求傳輸給對象實現(xiàn)后返回結果,在分布式網絡中間件中處于核心地位[3,4].
基于消息的網絡中間件主要用于在不同應用間投遞消息,專注于異構環(huán)境的消息交換,目前最流行的面向消息的網絡中間件是Apache的ActiveMQ.
消息可不包括語意和狀態(tài),因此面向消息的網絡中間件對應用而言是最透明的選擇.應用無需關心消息的來源、連接方式,而中間件無需關心消息的語意,這樣可以很好的實現(xiàn)與應用解耦[5–11].
此類中間件一般并不直接提供高級服務,而僅僅是負責對網絡業(yè)務進行封裝,降低編程復雜性,以ACE、boost.asio、libevent等為代表.
這些庫基本都實現(xiàn)了Reactor與Proactor設計模式,實現(xiàn)了高效的多路事件分離.下面以ACE庫為代表介紹其基本概念.
ACE自適配通信環(huán)境(ADAPTIVE Communication Environment)是可自由使用、開放源碼的面向對象構架(framework),它實現(xiàn)了許多用于并發(fā)通信軟件的核心模式.ACE提供了一組豐富的可重用C++包裝外觀(wrapper facade)和構架組件,可跨多種平臺完成通用的通信軟件任務,其中包括:事件多路分離和事件處理器分派、信號處理、服務初始化、進程間通信、共享內存管理、消息路由、分布式服務動態(tài)(重)配置、并發(fā)執(zhí)行和同步等[12–16].
以上網絡中間件雖然都是較為成熟的框架,但并不適用于大數(shù)據(jù)量、高性能要求的時序數(shù)據(jù)處理.首先、這些框架都是通用框架,針對時序數(shù)據(jù)的鍵值對特性無法優(yōu)化,使得通訊協(xié)議過于龐大而造成資源浪費;其次、通用框架需要考慮過多的場景,因此中間件過于復雜,例如CORBA就是一個重量級框架,將會拖累整個時序數(shù)據(jù)庫部署;再次、傳統(tǒng)中間件很好的屏蔽了底層操作系統(tǒng)相關性,做到通用性和跨平臺,但這是在損失一定的系統(tǒng)性能基礎上,因此無法滿足時序數(shù)據(jù)的大數(shù)據(jù)量和低響應時延的要求.
本文在設計高性能中間件時,提出了以下核心原則:
(1)盡量減少數(shù)據(jù)共享,以減少共享的互斥開銷.為此在中間件內部,所有的數(shù)據(jù)都設計為線程私有,兩個線程之間不存在共享數(shù)據(jù),數(shù)據(jù)通過消息進行傳遞,這樣減少了大量的互斥量、信號量、競爭條件等同步手段.
(2)每個線程異步且獨立運行,一個線程對其他線程沒有時間依賴性,不存在等待其他線程的時序一致性要求.線程間的協(xié)作請求、中間件內部命令也通過消息發(fā)送.每個線程維護自身的消息隊列,消息隊列除本線程外,僅有分發(fā)器可以訪問,不與其它線程共享.
(3)在本地盡量采用進程間管道進行通訊,在節(jié)點間通訊,可選點對點模式,減少中間件消息代理的負荷,提高效率并避免形成瓶頸.
根據(jù)上述原則,首先需要確定高性能中間件的并發(fā)模型,并發(fā)度的好壞決定了網絡中間件的性能優(yōu)劣.目前主流的并發(fā)模型有以下幾種:
表1 主流并發(fā)模型
時序數(shù)據(jù)客戶端進程的多個連接存在相關聯(lián)的可能性很小,且多個IO線程可明顯提高系統(tǒng)資源利用率,因此必須要有良好的線程擴展性;其次通知的異步調用有助于提高效率,線程池的設置則明顯減少了創(chuàng)建開銷.結合上述特點和七個方案的特性,我們最終選擇了方案7.
本文將整個系統(tǒng)內的線程分為兩種類型:應用線程(Application thread),在中間件以外由應用程序創(chuàng)建的業(yè)務線程,會訪問中間件的接口函數(shù)完成功能;核心線程 (Core thread/IO Thread),在中間件內部創(chuàng)建的線程,用于實際的功能實現(xiàn).
線程通過線程池進行管理,根據(jù)配置預先創(chuàng)建讀線程池和寫線程池,默認創(chuàng)建8個讀線程和8個寫線程,通過統(tǒng)一的線程管理器進行管理.讀寫線程池依據(jù)選擇的負載均衡算法,選定具體的處理線程,并將消息放入對應的線程消息隊列,網絡中間件默認選擇的策略為均衡輪循策略.線程對象關系圖如圖1.
圖1 線程對象關系
負載均衡策略池中包含多種負載均衡策略,有均衡輪循策略、隨機均衡策略、權重隨機均衡策略、響應速度均衡策略、最少連接數(shù)均衡策略等.讀寫線程池依據(jù)選擇的負載均衡算法,選定具體的處理線程.每一個讀寫線程池根據(jù)配置預先創(chuàng)建一定數(shù)量線程的讀線程池和寫線程池,通過統(tǒng)一的線程管理器進行管理,使用多線程進行IO讀寫可明顯提高系統(tǒng)資源利用率,而采用預先創(chuàng)建線程可以明顯減少后期頻繁創(chuàng)建銷毀線程的開銷.每個線程都有自己的消息隊列,從消息隊列中獲取處理報文.
2.2.1 消息格式設計
對于消息的要求一般來說比較復雜,因電力行業(yè)軟件在具有大量小尺寸應用消息的同時,也會有很多比較巨大的數(shù)據(jù)庫同步消息,同時由于消息的實際傳輸方式存在多種可能性,如兩個網絡節(jié)點間、同一節(jié)點的兩個應用之間、同一進程的兩個線程之間.對于小尺寸的消息而言,在棧上分配空間的開銷要遠小于在堆中分配-析構的開銷,因此對于小尺寸的消息應盡量在棧上分配,同時由于大尺寸的消息容易造成棧溢出,不可在棧上分配,因此對于不同大小的消息應提供不同的內存分配方案.且同一幀消息,有可能被發(fā)送至不同的接收端,如果接收方處于同一進程內,同一進程共享地址空間,消息拷貝沒有意義;如果消息體很大,拷貝代價很高,因此對于消息應提供引用計數(shù)的功能.
結合以上需求,對消息進行以下設計:
小尺寸消息在棧上分配,因大多數(shù)消息長度有限,如果使用內存操作符進行堆分配、析構,會造成性能瓶頸,也容易造成內存空間碎片,雖然部分中間件使用預先分配、統(tǒng)一使用的方式,但在棧上分配性能更佳.
大尺寸消息在堆上分配,防止棧溢出,同時支持引用計數(shù),以避免內存拷貝開銷,此外由于不同的應用,不同的系統(tǒng)可能有不同的內存管理機制,消息可支持外部特定的析構函數(shù).
小尺寸消息在棧上分配時,消息內容直接存儲在msg_buffer中,msg_buffer的長度由常量在編譯時指定.設計第一個Byte為消息類型(msg_type),第二個Byte為消息大小(msg_size,最大支持256),最后為256 Byte 的消息內容 (msg_buffer),由 msg_size 指定.消息結構如圖2所示.
圖2 消息結構
大尺寸消息,需要防止棧溢出,同時支持引用計數(shù)以避免大內存拷貝開銷,采用堆上分配方式,設計第一個 Byte為消息類型 (msg_type),第二個 Byte為空,其后 8–256 Byte用于記錄實際數(shù)據(jù)的地址 (dest),指向的地址空間包含數(shù)據(jù)的大小(size)、函數(shù)指針(Extern Func)、引用計數(shù)(Ref counter)和數(shù)據(jù)內容信息(User data).消息結構如圖3所示.
圖3 消息體結構
2.2.2 可擴展協(xié)議設計
傳統(tǒng)的網絡消息格式會被設計為消息頭(Message Head)+消息體(Message)的模式.如圖4所示.
圖4 傳統(tǒng)網絡消息格式
為了能對消息協(xié)議進行方便的擴充,本文引入了多幀消息的概念,通俗的說,每個消息可以有多個消息體組成.每一幀報文長度固定,由常量在編譯時指定,消息頭也被視為一個獨立的消息幀,這樣可以通過擴展消息幀數(shù)的方式擴展通訊協(xié)議.如圖5所示.
圖5 多幀消息結構
一個消息不再硬性的被區(qū)分為消息頭+消息體的機制,一個消息可以由多個消息幀組成.每個消息幀均為對等的獨立消息緩存,每一幀的大小固定.應用與中間件可以采用擴展消息幀的方式擴展通訊協(xié)議,而無須破壞現(xiàn)有結構與應用消息結構.
基于上述可擴展消息協(xié)議和負載均衡鏈接池并發(fā)模型,設計開發(fā)了時間序列數(shù)據(jù)庫高性能中間件組件,中間件主要包含兩個核心模塊:
OS_Wrapper為操作系統(tǒng)基礎接口封裝層,用于屏蔽不同操作系統(tǒng)底層調用的差異性,從而實現(xiàn)中間件的跨平臺.
WP_Network為高性能中間件的核心模塊,包含了協(xié)議解析、鏈接池管理分配、負載均衡實現(xiàn)等功能,該模塊位于OS_Wrapper之上,調用了OS_Wrapper封裝的底層接口.
電力系統(tǒng)時間序列數(shù)據(jù)庫會運行在Windows、Linux、Solaris、AIX等多種操作系統(tǒng)上,由于各個系統(tǒng)的數(shù)據(jù)類型、系統(tǒng)調用、線程管理、同步原語等均存在差異,為了保證跨平臺可移植性,采用OS_Wrapper來進行包裝,屏蔽差異性,主要有以下類組成:
表2 OS_Wrapper主要構成類
WP_Network是高性能中間件的核心功能模塊,其具有高性能、可擴展協(xié)議和負載均衡等特點,能有效節(jié)省網絡流量和提高響應速率.主要由以下多個類組成:
WP_Network中包含的類較多,邏輯也比較復雜,其中各類的靜態(tài)繼承和依賴關系如圖6所示.
本文研究了時間序列數(shù)據(jù)庫所需的高性能網絡中間件特點,并對其進行了開發(fā)實現(xiàn),本文所涉及的網絡中間件已經運用于PCS-9000時間序列數(shù)據(jù)中.采用上述方案后,高性能中間件具有以下特點:
(1)不需要為每個客戶端創(chuàng)建處理線程,降低了系統(tǒng)資源開銷,支持客戶端最大并發(fā)數(shù)顯著提高;
表3 WP_Network 主要構成類
圖6 WP_Network 主要結構
(2)顯著提高報文處理能力,每秒可處理500萬事件(記錄);
(3)降低了網絡流量,服務端占用的CPU和內存明顯減少.
表4 與國內外主流時間序列數(shù)據(jù)庫比較
時間序列數(shù)據(jù)庫在國內外都有廣泛應用,主流產品如海迅時間序列數(shù)據(jù)庫、PI時間序列數(shù)據(jù)庫、eDNA時間序列數(shù)據(jù)庫等.相比較,PCS-9000時間序列數(shù)據(jù)庫具有以下的優(yōu)勢:
綜上所述,高性能中間件技術的引入大大提高了時間序列數(shù)據(jù)庫的處理能力,降低了系統(tǒng)和網絡資源的開銷,使得同樣硬件資源可以實現(xiàn)更高數(shù)據(jù)量的存儲,具有推廣意義.