王 榮,王建新,陳 向,盛 羽
中南大學(xué) 信息科學(xué)與工程學(xué)院,長(zhǎng)沙 410083
數(shù)字圖像處理作為一門非常實(shí)用的學(xué)科,它一直是高校教學(xué)的重點(diǎn)和難點(diǎn)。學(xué)生通過(guò)實(shí)驗(yàn)對(duì)所學(xué)的算法進(jìn)行實(shí)現(xiàn)、改進(jìn)以及重新設(shè)計(jì),并對(duì)算法的處理效果進(jìn)行分析和比較,從而能增進(jìn)對(duì)算法的了解[1]。數(shù)字圖像算法抽象,涉及的公式一般比較復(fù)雜。學(xué)生可以通過(guò)C、C++[2]和Java[3]等高級(jí)編程語(yǔ)言來(lái)實(shí)現(xiàn)數(shù)字圖像處理算法,也可以調(diào)用MATLAB圖像處理工具箱[4-5]、OPenCV[6]和ImageJ]7]集成的數(shù)字圖像算法庫(kù)構(gòu)建復(fù)雜的實(shí)驗(yàn)流程。不論是自己編程還是使用MATLAB和OPenCV等提供的圖像處理工具都需要配置硬件設(shè)施和運(yùn)行環(huán)境,在預(yù)定的機(jī)器上進(jìn)行實(shí)驗(yàn)。顯然在移動(dòng)設(shè)備上傳統(tǒng)模式不能很好地支撐,用戶無(wú)法隨時(shí)隨地進(jìn)行實(shí)驗(yàn)。文獻(xiàn)[8]提出了基于Khoros平臺(tái)開發(fā)的數(shù)字圖像處理系統(tǒng),該系統(tǒng)實(shí)現(xiàn)了豐富的圖像處理算法,并提供了Internet的訪問(wèn)功能,但是該系統(tǒng)沒(méi)有提供靈活的實(shí)驗(yàn)流程定制方案,缺乏交互性。文獻(xiàn)[9]提出了基于CORBA技術(shù)的多語(yǔ)言集成平臺(tái),但是CORBA技術(shù)使用IIOP協(xié)議很難穿透防火墻,因此該平臺(tái)只適用于局域網(wǎng)內(nèi)部的資源集成,無(wú)法實(shí)現(xiàn)跨Internet的異構(gòu)資源集成和計(jì)算協(xié)同。文獻(xiàn)[10]提出了異構(gòu)資源集成的虛擬實(shí)驗(yàn)平臺(tái),該系統(tǒng)采用Web服務(wù)技術(shù)實(shí)現(xiàn)了Java和MATLAB的集成,在定制實(shí)驗(yàn)流程和實(shí)現(xiàn)組件的分布式管理方面做了探索和研究,取得了有益的進(jìn)展。但是該系統(tǒng)的客戶端使用Applet,通過(guò)RMI/IIOP直接訪問(wèn)JavaBean來(lái)獲得信息,迫使防火墻開放相應(yīng)信息的端口,使系統(tǒng)存在潛在的不安全性隱患。
針對(duì)以上問(wèn)題,本文設(shè)計(jì)并實(shí)現(xiàn)了一個(gè)面向異構(gòu)資源集成的數(shù)字圖像實(shí)驗(yàn)平臺(tái)。該平臺(tái)實(shí)現(xiàn)了以下目標(biāo):
(1)支持多種語(yǔ)言編寫的算法組件間的交互。所支持的編程語(yǔ)言包括:Java、C++、Python、MATLAB 和OpenCV等工具軟件。
(2)支持用戶將自己編寫的算法源代碼按照平臺(tái)的相應(yīng)規(guī)則提交到平臺(tái)中并與平臺(tái)其他代碼集成運(yùn)行。
(3)支持用戶自行選擇圖像算法組件構(gòu)建實(shí)驗(yàn)流程。
針對(duì)以上設(shè)計(jì)目標(biāo),本文提出的平臺(tái)架構(gòu)如圖1所示。平臺(tái)主要由Nignx服務(wù)器、Web應(yīng)用服務(wù)器、實(shí)驗(yàn)調(diào)度服務(wù)器、算法組件服務(wù)集群和數(shù)據(jù)庫(kù)存儲(chǔ)服務(wù)器5部分組成,各部分的作用如下:
(1)Nignx服務(wù)器:負(fù)載均衡服務(wù)器處理用戶請(qǐng)求。采用ip_hash作為負(fù)載均衡方式來(lái)實(shí)現(xiàn)session共享和解決文件上傳下載的問(wèn)題,使同一個(gè)用戶的請(qǐng)求對(duì)應(yīng)訪問(wèn)同一個(gè)后端服務(wù)器。
(2)Web應(yīng)用服務(wù)器:用戶通過(guò)Internet與Web應(yīng)用服務(wù)器進(jìn)行交互,比如用戶提交自定義組件、注冊(cè)組件服務(wù)和創(chuàng)建實(shí)驗(yàn)流程等。Web應(yīng)用服務(wù)器采用MVC模式將操作界面、數(shù)據(jù)模型和業(yè)務(wù)邏輯解耦和。表示層向用戶提供友好的實(shí)驗(yàn)操作界面,用戶請(qǐng)求控制器對(duì)封裝的實(shí)驗(yàn)或組件數(shù)據(jù)進(jìn)行解析。控制器用來(lái)接收用戶提交的請(qǐng)求,將請(qǐng)求傳來(lái)的JSON數(shù)據(jù)轉(zhuǎn)換成模型中對(duì)應(yīng)的數(shù)據(jù)模型,然后調(diào)用相應(yīng)的業(yè)務(wù)方法并根據(jù)調(diào)用結(jié)果選擇返回視圖。
(3)數(shù)據(jù)庫(kù)存儲(chǔ)服務(wù)器:負(fù)責(zé)平臺(tái)數(shù)據(jù)的持久化存儲(chǔ),主要存儲(chǔ)組件、實(shí)驗(yàn)信息和監(jiān)控信息等。平臺(tái)對(duì)數(shù)據(jù)一致性和復(fù)雜查詢沒(méi)有特別需求,因此采用了流行的NoSQL數(shù)據(jù)庫(kù)MongoDB[11],搭建一主兩從的集群,提高了數(shù)據(jù)高并發(fā)讀寫效率和降低了擴(kuò)展難度。
(4)調(diào)度服務(wù)器:采用線程池技術(shù)異步獲取處于待處理的實(shí)驗(yàn)并采用RPC技術(shù)遠(yuǎn)程調(diào)用算法組件服務(wù)器的服務(wù)接口進(jìn)行實(shí)驗(yàn)處理,最后負(fù)責(zé)將實(shí)驗(yàn)結(jié)果進(jìn)行持久化存儲(chǔ)。
(5)算法組件服務(wù)集群:承載了C++、MATLAB、Java和Python等語(yǔ)言的算法組件同時(shí)提供對(duì)外服務(wù)接口,算法服務(wù)之間通過(guò)RPC技術(shù)進(jìn)行信息傳遞。為了提高算法組件運(yùn)行速度,確保算法服務(wù)器的可維護(hù)性,后臺(tái)集群按照語(yǔ)言種類進(jìn)行機(jī)器資源的分配,即不同語(yǔ)言使用不同的機(jī)器對(duì)外提供服務(wù)。

圖1 平臺(tái)架構(gòu)圖
數(shù)字圖像處理課程實(shí)驗(yàn)中的核心為各種圖像處理算法,學(xué)生通過(guò)各種算法的組合來(lái)完成實(shí)驗(yàn)以獲取圖像處理結(jié)果。為了提高用戶實(shí)驗(yàn)的便利性,實(shí)現(xiàn)對(duì)多語(yǔ)言的支持,平臺(tái)將各種數(shù)字圖像常用的算法進(jìn)行構(gòu)件化,以供用戶選擇、組合和使用。
平臺(tái)中的算法構(gòu)件主要包括算法核心代碼、算法相關(guān)參數(shù)、Thrif框架代碼等幾個(gè)方面。其中Thrift框架代碼為算法服務(wù)的調(diào)用提供相關(guān)接口,算法核心代碼則是實(shí)現(xiàn)算法功能的核心部分,算法相關(guān)參數(shù)則包括上下文參數(shù)和屬性參數(shù)兩種。上下文參數(shù)即算法的輸入和輸出參數(shù),在本平臺(tái)中,輸入輸出參數(shù)均為數(shù)字圖像類型。屬性參數(shù)則是算法執(zhí)行過(guò)程中對(duì)算法執(zhí)行結(jié)果產(chǎn)生影響的參數(shù)。
算法構(gòu)件交互涉及4種角色:服務(wù)發(fā)布者、服務(wù)注冊(cè)中心、算法服務(wù)群和服務(wù)請(qǐng)求者。角色交互如圖2所示。

圖2 組件服務(wù)化交互圖
服務(wù)發(fā)布者在平臺(tái)的Web界面中提交算法的核心代碼并配置相關(guān)的參數(shù)。平臺(tái)將對(duì)用戶所提交的核心代碼進(jìn)行編譯并將編譯通過(guò)的代碼,相關(guān)參數(shù)與Thrift框架進(jìn)行融合形成Thrift服務(wù)構(gòu)件形成服務(wù)群,并將調(diào)用信息發(fā)布到注冊(cè)中心,從而完成算法構(gòu)件的發(fā)布。算法構(gòu)件的核心屬性包括serviceUrl、nameSpace、method-Name、comDepict和 paramArr。serviceUrl記錄組件服務(wù)地址,包含調(diào)用服務(wù)的IP和端口號(hào),它決定了調(diào)用分布式服務(wù)的地址。nameSpace記錄組件服務(wù)名,method-Name記錄組件調(diào)用方法名,paramArr用來(lái)表示參數(shù)信息列表。參數(shù)屬性的校驗(yàn),則是用算法服務(wù)器對(duì)算法解析得到的參數(shù)跟用戶注冊(cè)組件描述的參數(shù)進(jìn)行匹配的過(guò)程。對(duì)于從算法源碼層面解析獲取參數(shù)的方式,Java根據(jù)用戶注冊(cè)提交的調(diào)用方法,通過(guò)反射機(jī)制獲得方法的參數(shù)類型、參數(shù)名和返回值類型。MATLAB和C++則通過(guò)文本解析得到算法組件代碼的參數(shù)定義行,從而解析出方法的參數(shù)名、參數(shù)類型和參數(shù)返回值。
組件服務(wù)調(diào)用則是處理實(shí)驗(yàn)流程中組件之間的交互。根據(jù)用戶的偏好,各算法組件可能由不同的編程語(yǔ)言來(lái)開發(fā),因此平臺(tái)需要提供跨語(yǔ)言的程序調(diào)用。目前支持跨語(yǔ)言遠(yuǎn)程調(diào)用的技術(shù)主要有:阿里巴巴的Dubbo[12]、Hsf[13],F(xiàn)acebook 的 Thrift[14],Google的 Grpc[15],Twitter的Finagle等[16]。在這些RPC中,F(xiàn)acebook的Thrift支持更多語(yǔ)言的消息格式,它具有自己內(nèi)部定義的傳輸協(xié)議規(guī)范和傳輸數(shù)據(jù)標(biāo)準(zhǔn),可以和已經(jīng)有的Web服務(wù)器進(jìn)行無(wú)縫組合,同時(shí)它還為服務(wù)器提供了多種模式的運(yùn)行機(jī)制,包含阻塞、非阻塞,單線程和多線程等。Thrift文件生成的目標(biāo)代碼簡(jiǎn)單易用,包含完整的客戶端/服務(wù)端堆棧,能快速實(shí)現(xiàn)RPC,因此Atlas使用Thrift搭建虛擬實(shí)驗(yàn)室平臺(tái)調(diào)度系統(tǒng)之間的橋梁,通過(guò)運(yùn)行腳本對(duì)傳輸數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)和業(yè)務(wù)邏輯根據(jù)不同的運(yùn)行環(huán)境快速構(gòu)建相應(yīng)的代碼,同時(shí)根據(jù)Thrift內(nèi)部序列化機(jī)制對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行簡(jiǎn)化和壓縮。綜合平臺(tái)需求和Thrift技術(shù),本文設(shè)計(jì)Thrift接口腳本文件ImageTService,只需用Thrift腳本語(yǔ)言把下面的IDL編譯成對(duì)應(yīng)語(yǔ)言的客戶端和服務(wù)端,就可以實(shí)現(xiàn)異構(gòu)語(yǔ)言間的相互調(diào)用,腳本內(nèi)容如下所示:
struct ErrorCodeType{
1:i32 errorCode,
2:optional string message,
}
exception ImageTException{
1:i32 errorCode,
2:optional string message,
}
struct KeyValue{
1:string key,
2:optional string value,
3:bool pid,
}
struct ImageTResult{
1:ErrorCodeType errorCodeType,
}
service ImageTService{
ImageTResultexecute(1:stringcodeName,2:string codeUrl,3:string codeMethod,4:list
ImageTResultfixParameter(1:string id,2:KeyValue keyValue,3:String runPath)throws(1:ImageTException e)
}
ImageTService服務(wù)接口中的execute方法是組件對(duì)調(diào)度服務(wù)器提供的調(diào)用方法,在調(diào)度服務(wù)器向算法服務(wù)器傳輸組件信息時(shí)被調(diào)用。調(diào)度服務(wù)器處理實(shí)驗(yàn)流程時(shí)會(huì)去注冊(cè)中心查詢算法服務(wù)的調(diào)用地址,并將實(shí)驗(yàn)流程中的算法組件進(jìn)行信息初始化和任務(wù)的分發(fā)。code-Name、codeUrl和codeMethod唯一確定服務(wù)調(diào)用的定位信息,keyvalues則為組件初始化參數(shù)對(duì)象列表,nextNodeArr表示組件對(duì)象的子節(jié)點(diǎn)調(diào)用信息集合,算法服務(wù)器接收到調(diào)度服務(wù)器請(qǐng)求時(shí),會(huì)將當(dāng)前任務(wù)插入準(zhǔn)備隊(duì)列,等待父組件信息傳遞直到組件運(yùn)行參數(shù)就緒,該組件會(huì)被移動(dòng)到就緒隊(duì)列等待服務(wù)的啟動(dòng),組件運(yùn)行完成后,會(huì)依次調(diào)用子節(jié)點(diǎn)的fixParameter方法將運(yùn)行結(jié)果傳遞下去。在fixParameter方法中,id用來(lái)唯一確定準(zhǔn)備隊(duì)列中的組件任務(wù),keyValue則為父節(jié)點(diǎn)的運(yùn)行結(jié)果信息,runPath紀(jì)錄了當(dāng)前鏈路的運(yùn)行路徑。ImageTResult定義返回結(jié)果,包含錯(cuò)誤信息結(jié)構(gòu)體ImageTException,由錯(cuò)誤碼和錯(cuò)誤信息組成。
算法服務(wù)器會(huì)啟動(dòng)線程池同步的拿取就緒隊(duì)列中的組件并異步的處理組件服務(wù),對(duì)于Java語(yǔ)言實(shí)現(xiàn)的算法服務(wù),類加載器將組件服務(wù)源碼加載到JVM中,根據(jù)算法組件的信息實(shí)例化組件對(duì)象,封裝反射所需的參數(shù)來(lái)調(diào)用對(duì)應(yīng)的方法服務(wù)。對(duì)于MATLAB組件,采用命令行的形式封裝當(dāng)前組件的調(diào)用參數(shù)并運(yùn)行組件算法。對(duì)于C++算法服務(wù)器,圖像處理部分借助于OpenCV,用戶借助其內(nèi)置函數(shù)進(jìn)行圖像處理,也可以遍歷圖像的每一個(gè)像素點(diǎn),除此之外還可以自己編寫圖像處理程序。對(duì)于Python算法服務(wù)器,借助于免費(fèi)庫(kù)PIL輔助對(duì)算法組件進(jìn)行處理。
在虛擬實(shí)驗(yàn)平臺(tái)的交互端,用戶根據(jù)實(shí)驗(yàn)需要,選擇虛擬實(shí)驗(yàn)儀器,通過(guò)連線創(chuàng)建實(shí)驗(yàn)流程,這個(gè)過(guò)程的數(shù)據(jù)模型和操作面板的友好可用是影響用戶體驗(yàn)的關(guān)鍵步驟。該平臺(tái)的實(shí)驗(yàn)流程圖和組件列表樹都是通過(guò)JavaScript交互圖庫(kù)GoJS來(lái)實(shí)現(xiàn)的。GoJS是一種模型-視圖結(jié)構(gòu),視圖是模型的可視化,模型是視圖的數(shù)據(jù)體現(xiàn),模型的節(jié)點(diǎn)數(shù)組和連線數(shù)組跟視圖的節(jié)點(diǎn)模板和連線模板一一對(duì)應(yīng)。
圖3為客戶端實(shí)驗(yàn)流程創(chuàng)建過(guò)程中視圖和數(shù)據(jù)的交互過(guò)程。進(jìn)入新建實(shí)驗(yàn)頁(yè)面時(shí),瀏覽器會(huì)向Web端發(fā)送get請(qǐng)求,客戶端把返回的算法組件信息列表解析成菜單樹數(shù)據(jù)模型和可視化展示的菜單樹,同時(shí)會(huì)初始化一個(gè)實(shí)驗(yàn)面板Diagram。選擇組件時(shí),會(huì)在實(shí)驗(yàn)面板中展示對(duì)應(yīng)的節(jié)點(diǎn)面板(NodeTemplates)同時(shí)在數(shù)據(jù)模型層的節(jié)點(diǎn)數(shù)組(NodeDataArray)中添加相應(yīng)的數(shù)據(jù)。添加連線時(shí),會(huì)在實(shí)驗(yàn)面板中展示對(duì)應(yīng)的連線面板(Link-Templates)同時(shí)會(huì)在數(shù)據(jù)模型層的連線數(shù)(LinkData-Array)添加連線的數(shù)據(jù)信息。用戶通過(guò)選擇算法組件,修改組件參數(shù)、添加連線創(chuàng)建一個(gè)完整的實(shí)驗(yàn)流程圖。數(shù)據(jù)模型GraphLinksModel是客戶端跟Web應(yīng)用服務(wù)器進(jìn)行交互的數(shù)據(jù)媒介,實(shí)驗(yàn)面板Diagram則作為GraphLinksModel的可視化界面展示供用戶操作。

圖3 實(shí)驗(yàn)前臺(tái)數(shù)據(jù)交互模型
客戶端的圖像模板與數(shù)據(jù)模型之間的交互保證了用戶操作的體驗(yàn),Web應(yīng)用服務(wù)器對(duì)數(shù)據(jù)的解析和對(duì)實(shí)驗(yàn)持久化存儲(chǔ)則為調(diào)度集群鑒定了基石。對(duì)于客戶端傳來(lái)的數(shù)據(jù)模型,Web應(yīng)用服務(wù)端的控制層會(huì)根據(jù)連線對(duì)象,完善組件對(duì)象信息,例如組件對(duì)象A、B、C,存在A?B連線和A?C連線,完善A組件的nextNodeArr為B、C。
為了降低系統(tǒng)之間的耦合性,提高系統(tǒng)的健壯性,平臺(tái)將調(diào)度系統(tǒng)與Web應(yīng)用服務(wù)器進(jìn)行了分離,它們通過(guò)持久層進(jìn)行信息交互。調(diào)度服務(wù)器是實(shí)驗(yàn)運(yùn)行的核心環(huán)節(jié),合理的調(diào)度機(jī)制直接關(guān)系著整個(gè)平臺(tái)的并發(fā)能力。
數(shù)字圖像虛擬實(shí)驗(yàn)平臺(tái)中,包含多種不同語(yǔ)言的異構(gòu)服務(wù)組件。這些組件之間在功能上相互獨(dú)立,用戶可以用連線將它們組合成一個(gè)有機(jī)整體。在設(shè)計(jì)得較為復(fù)雜的實(shí)驗(yàn)流程中,組件之間的連接關(guān)系變得異常復(fù)雜,為了保證實(shí)驗(yàn)有序高效地執(zhí)行,設(shè)計(jì)了一個(gè)合理的實(shí)驗(yàn)運(yùn)行調(diào)度機(jī)制。
一個(gè)完整的實(shí)驗(yàn)流程,可以抽象為數(shù)據(jù)結(jié)構(gòu)里的有向圖。流程圖中的組件可以抽象為有向圖中的頂點(diǎn),組件間的連接線可以抽象為有向圖中的邊,實(shí)驗(yàn)中組件結(jié)果數(shù)據(jù)的流動(dòng)方向與有向邊的方向一致。實(shí)驗(yàn)的順利執(zhí)行需要嚴(yán)格按照組件的先后順序。從圖論上看實(shí)驗(yàn)中組件的運(yùn)行順序符合圖的拓?fù)渑判蝽樞颍庸?jié)點(diǎn)的輸入?yún)?shù)依賴父節(jié)點(diǎn)的輸出參數(shù),即父節(jié)點(diǎn)的運(yùn)行總是優(yōu)先于子節(jié)點(diǎn)的運(yùn)行,值得注意的是實(shí)驗(yàn)流程中不允許存在環(huán)以避免組件的無(wú)限循環(huán)運(yùn)行。實(shí)驗(yàn)中的組件流程按照?qǐng)D的拓?fù)渑判蚪Y(jié)果順序執(zhí)行,即可完成一次實(shí)驗(yàn)調(diào)度。采用這種方式設(shè)計(jì)實(shí)驗(yàn)運(yùn)行調(diào)度機(jī)制,比較簡(jiǎn)單,只需要先對(duì)實(shí)驗(yàn)流程的抽象有向圖進(jìn)行拓?fù)渑判颍缓笾饌€(gè)執(zhí)行組件。假設(shè)A、C、B是相互異構(gòu)的組件,A、B為C的父節(jié)點(diǎn),A1、B1、C1分別是A、B、C節(jié)點(diǎn)對(duì)應(yīng)的服務(wù)端服務(wù)。按照拓?fù)渑判蛘{(diào)度方式,運(yùn)行順序?yàn)锳、B、C。調(diào)度系統(tǒng)執(zhí)行過(guò)程為:(1)調(diào)度服務(wù)器去注冊(cè)中心查詢A的服務(wù)地址A1,封裝服務(wù)接口需要的信息并遠(yuǎn)程調(diào)用A1服務(wù),存儲(chǔ)A1服務(wù)結(jié)果到緩存。(2)調(diào)度服務(wù)器去注冊(cè)中心查詢B的服務(wù)地址B1,封裝服務(wù)接口需要的信息遠(yuǎn)程調(diào)用B1服務(wù),存儲(chǔ)B1服務(wù)結(jié)果到緩存。(3)調(diào)度服務(wù)器去注冊(cè)中心查詢C的服務(wù)地址C1,根據(jù)A1和B1服務(wù)運(yùn)行結(jié)果完善服務(wù)接口調(diào)用信息并遠(yuǎn)程調(diào)用C1服務(wù),存儲(chǔ)C1服務(wù)結(jié)果作為C子節(jié)點(diǎn)的輸入?yún)?shù)。分析這個(gè)過(guò)程,調(diào)度服務(wù)器和服務(wù)集群中存在2N次數(shù)據(jù)傳輸,N為算法組件的個(gè)數(shù),很顯然A和B組件在執(zhí)行時(shí)是可以并發(fā)執(zhí)行而不存在先后順序。
為了減少數(shù)據(jù)傳輸次數(shù),保證系統(tǒng)的穩(wěn)定性,提高系統(tǒng)的并發(fā)性能,本文提出了一種新的調(diào)度機(jī)制,組件的運(yùn)行順序不再嚴(yán)格地依賴拓?fù)渑判虻慕Y(jié)果。如圖1所示,調(diào)度服務(wù)器負(fù)責(zé)與服務(wù)注冊(cè)中心和數(shù)據(jù)持久層進(jìn)行交互,對(duì)實(shí)驗(yàn)流程圖中各個(gè)組件的信息進(jìn)行封裝,并將組件服務(wù)任務(wù)一次性下發(fā)到對(duì)應(yīng)的算法服務(wù)器上。調(diào)度服務(wù)器此時(shí)化身接收返回鏈路結(jié)果的服務(wù)端來(lái)與數(shù)據(jù)持久層交互。算法服務(wù)器用準(zhǔn)備隊(duì)列和就緒隊(duì)列用來(lái)存儲(chǔ)算法組件任務(wù),對(duì)于需要父類組件結(jié)果的組件任務(wù),會(huì)被插入到準(zhǔn)備隊(duì)列中,直到父類的參數(shù)到達(dá)方可移到就緒隊(duì)列中等待服務(wù)被調(diào)用。對(duì)上面的例子用這種模式處理過(guò)程如下:(1)調(diào)度服務(wù)器封裝A、B、C組件的參數(shù)信息,去注冊(cè)中心查詢組件服務(wù)地址A1、B1、C1,并遠(yuǎn)程調(diào)用算法服務(wù)器的execute方法服務(wù),將組件任務(wù)分發(fā)到各自的服務(wù)器。(2)A和B組件參數(shù)就緒時(shí)被移到各自服務(wù)器上的就緒隊(duì)列等待服務(wù)的運(yùn)行,運(yùn)行結(jié)束后,根據(jù)組件nextNodeArr中存儲(chǔ)的next節(jié)點(diǎn)信息,調(diào)用C1服務(wù)器中fixParameter方法服務(wù)將處理結(jié)果傳遞給處于準(zhǔn)備隊(duì)列中的C組件。(3)C組件獲得父組件A和B傳來(lái)的結(jié)果,從準(zhǔn)備隊(duì)列轉(zhuǎn)到了就緒隊(duì)列等待服務(wù)運(yùn)行。(4)如果C組件nextNodeArr中存儲(chǔ)的是end節(jié)點(diǎn)信息,C1服務(wù)器處理完C組件后會(huì)將結(jié)果傳遞給調(diào)度服務(wù)器,調(diào)度服務(wù)器將實(shí)驗(yàn)結(jié)果持久化存儲(chǔ),供Web服務(wù)器輪詢查詢結(jié)果并在客戶端可視化顯示,否則C組件繼續(xù)向下傳遞結(jié)果。在以上調(diào)度基礎(chǔ)上繼續(xù)優(yōu)化該模式,假設(shè)A、C的服務(wù)在同一臺(tái)算法服務(wù)器上,則把A、C組件視為一個(gè)調(diào)度集。A、C之間不需要將運(yùn)行結(jié)果通過(guò)網(wǎng)絡(luò)傳輸,算法服務(wù)器處理時(shí),對(duì)nextNodeArr中的next節(jié)點(diǎn)信息與當(dāng)前服務(wù)地址進(jìn)行匹對(duì)。如果與當(dāng)前組件地址相同,則直接進(jìn)行參數(shù)賦值,實(shí)驗(yàn)創(chuàng)建到調(diào)度結(jié)束結(jié)果返回的時(shí)序圖,如圖4。
對(duì)以上兩種運(yùn)行流程進(jìn)行比較,可以看出對(duì)等模型相對(duì)于傳統(tǒng)模型的優(yōu)勢(shì):(1)摒棄了傳統(tǒng)拓?fù)渑判虻耐耆樞驁?zhí)行模式。當(dāng)多個(gè)組件同時(shí)處于就緒狀態(tài)時(shí),可以并發(fā)執(zhí)行,類似于上例中的A、B組件,減少了實(shí)驗(yàn)運(yùn)行時(shí)間。(2)假設(shè)當(dāng)前實(shí)驗(yàn)有M組相連組件在同一臺(tái)算法服務(wù)器上和N個(gè)剩余組件,按照傳統(tǒng)的拓?fù)渑判蚰J骄W(wǎng)絡(luò)傳輸次數(shù)為。Ji表示第i組相連組件的個(gè)數(shù),當(dāng)前模型傳輸次數(shù)降低為N+M次。(3)可以異步返回獨(dú)立鏈路的實(shí)驗(yàn)結(jié)果,一條鏈路出錯(cuò)不影響另外一條鏈路正常運(yùn)行。(4)與拓?fù)渑判蛞粯樱梢垣@得實(shí)驗(yàn)的鏈路運(yùn)行路徑。(5)不需要結(jié)果緩存層對(duì)中間結(jié)果進(jìn)行存儲(chǔ),直接把運(yùn)行結(jié)果傳遞給下一個(gè)組件。(6)圖中若存在多條鏈路,實(shí)驗(yàn)內(nèi)部可以并發(fā)執(zhí)行,減少了實(shí)驗(yàn)的運(yùn)行時(shí)間,提高了實(shí)驗(yàn)的容錯(cuò)率。
多線程機(jī)制是確定Web應(yīng)用服務(wù)器、調(diào)度服務(wù)器和算法組件服務(wù)器高并發(fā)、高性能的關(guān)鍵。采用多線程可以使CPU在不同任務(wù)間不停切換,減少了CPU的空閑時(shí)間,降低了子任務(wù)平均等待的時(shí)間。但是在高并發(fā)系統(tǒng)中,頻繁的創(chuàng)建和銷毀線程不但浪費(fèi)時(shí)間,而且降低系統(tǒng)運(yùn)行效率。尤其在面向?qū)ο缶幊讨校瑒?chuàng)建線程對(duì)象要JVM分配相應(yīng)的堆棧內(nèi)存,運(yùn)行前還要確保類被加載器加載到靜態(tài)存儲(chǔ)區(qū)。為了防止堆棧溢出,虛擬機(jī)會(huì)通過(guò)引用可達(dá)算法追蹤每一個(gè)對(duì)象的生命周期,確保能對(duì)銷毀的線程對(duì)象及時(shí)進(jìn)行垃圾回收。除此之外,線程過(guò)多還會(huì)導(dǎo)致內(nèi)存溢出和線程間切換頻繁導(dǎo)致服務(wù)器崩潰。線程池通過(guò)限制最大線程數(shù)量和重復(fù)利用已創(chuàng)建的線程解決了以上問(wèn)題,它將創(chuàng)建開銷分?jǐn)偟搅硕鄠€(gè)請(qǐng)求任務(wù)上,當(dāng)請(qǐng)求到達(dá)且有線程空閑時(shí),該請(qǐng)求直接被處理,消除了創(chuàng)建線程的延遲,提高了響應(yīng)速度。
進(jìn)程是系統(tǒng)資源分配的基本單位,進(jìn)程的資源和地址空間同時(shí)被多個(gè)子線程共享。當(dāng)多個(gè)線程同時(shí)訪問(wèn)某個(gè)資源時(shí),存在資源同步問(wèn)題。在調(diào)度服務(wù)器和算法服務(wù)器中,多個(gè)線程同時(shí)訪問(wèn)臨界資源會(huì)產(chǎn)生寫丟失、臟數(shù)據(jù)等線程安全問(wèn)題。例如調(diào)度服務(wù)器多個(gè)線程同時(shí)獲取數(shù)據(jù)存儲(chǔ)層處于等待運(yùn)行狀態(tài)的實(shí)驗(yàn),算法服務(wù)器多個(gè)線程同時(shí)獲取就緒隊(duì)列待運(yùn)行的組件。為了解決對(duì)臨界資源訪問(wèn)的安全問(wèn)題,平臺(tái)采用“序列化訪問(wèn)資源”方法,通過(guò)給臨界資源代碼塊加鎖,確保臨界資源在同一時(shí)刻只有一個(gè)線程訪問(wèn)。調(diào)度服務(wù)器則對(duì)獲取待運(yùn)行實(shí)驗(yàn)并更改實(shí)驗(yàn)狀態(tài)這個(gè)過(guò)程加鎖。算法服務(wù)器中,對(duì)獲取待運(yùn)行組件并更改組件狀態(tài)這個(gè)過(guò)程加鎖,實(shí)現(xiàn)了對(duì)臨界資源的互斥訪問(wèn)。

圖4 算法調(diào)度時(shí)序圖
線程池?cái)?shù)量設(shè)置過(guò)小不能充分利用服務(wù)器資源,設(shè)置過(guò)大則會(huì)造成線程上下文頻繁切換甚至?xí)捎谡加孟到y(tǒng)資源過(guò)多導(dǎo)致服務(wù)器宕機(jī),合理的線程數(shù)目是確保系統(tǒng)高并發(fā)運(yùn)行的基礎(chǔ)。經(jīng)過(guò)調(diào)研分析得:對(duì)于CPU密集型應(yīng)用,線程池大小一般設(shè)置為N+1,對(duì)于IO密集型應(yīng)用,線程池大小一般設(shè)置為2N+1,N為CPU的核數(shù)。目前數(shù)字圖像處理平臺(tái)服務(wù)器機(jī)器的CPU都是8核,為了得到調(diào)度的最佳線程數(shù)量,對(duì)調(diào)度系統(tǒng)線程池大小用二分法進(jìn)行性能測(cè)試,測(cè)試區(qū)間值為10~25個(gè),經(jīng)過(guò)分析得線程池的最佳大小配置之一為20個(gè),初始化4組scheduledExecutorTasks,首次執(zhí)行分別延時(shí)0.5 s、1 s、1.5 s、2.0 s,之后采用非固定間隔每隔3 s定期啟動(dòng)線程處理實(shí)驗(yàn)任務(wù),直到線程數(shù)量達(dá)到20。
平臺(tái)中的Thrift服務(wù)使用非堵塞I/O模型作為多線程服務(wù)器端來(lái)處理大量并發(fā)連接請(qǐng)求。如圖5所示,AcceptThread線程對(duì)象來(lái)監(jiān)聽socket上的新連接,負(fù)載均衡器決定將請(qǐng)求分配給哪個(gè)SelectorThread對(duì)象,SelectorThread對(duì)象處理網(wǎng)絡(luò)I/O操作,同時(shí)把具體的調(diào)用執(zhí)行交給ExecutorService線程池中的線程。這種模式下,線程AcceptThread處理連接請(qǐng)求確保了能夠及時(shí)對(duì)大量并發(fā)連接請(qǐng)求做出響應(yīng),除此之外,以將網(wǎng)絡(luò)I/O分散到多個(gè)SelectorThread線程的方式加速了網(wǎng)絡(luò)I/O的讀寫操作。

圖5 Thrift服務(wù)端工作模式
總體而言,虛擬實(shí)驗(yàn)平臺(tái)采用了同步代碼塊和線程池的技術(shù)保證了系統(tǒng)的高可用和高并發(fā)。
根據(jù)前面提到的系統(tǒng)架構(gòu)和關(guān)鍵技術(shù),實(shí)現(xiàn)了面向異構(gòu)資源集成的數(shù)字圖像虛擬實(shí)驗(yàn)室平臺(tái)。該平臺(tái)公共組件庫(kù)包含了多種語(yǔ)言(MATLAB、Java、C++和Python等)實(shí)現(xiàn)的常用的數(shù)字圖像處理算法,例如灰度變換、繪制直方圖、空間濾波、頻率濾波、邊緣檢測(cè)和傅里葉變換等數(shù)百種算法。除了系統(tǒng)的公共組件外,用戶也可以把用自己熟悉語(yǔ)言開發(fā)的組件集成到平臺(tái)中,通過(guò)異構(gòu)組件發(fā)布的方式發(fā)布為Web服務(wù)組件,提高組件的復(fù)用性。
圖6給出了創(chuàng)建實(shí)驗(yàn)的界面,菜單欄顯示了當(dāng)前用戶的功能模塊,左側(cè)面板是組件列表,包含基本輸入、輸出組件、公共組件和用戶組件。公共組件和用戶組件下面又包含了MATLAB、Java、C++、Python組件的子目錄,左下角面板顯示當(dāng)前組件的描述信息,中間面板是實(shí)驗(yàn)流程搭建面板,右邊側(cè)欄是組件屬性參數(shù)配置欄。以搭建“通過(guò)圖像灰度變換與空間濾波來(lái)模擬空間域圖像增強(qiáng)”實(shí)驗(yàn)為例,首先根據(jù)個(gè)性化流程在組件列表欄選擇需要的組件:輸入圖像組件imread,結(jié)果顯示組件imshow,灰度變換組件Rgbtogray(Java),中值濾波組件Medfilter(MATLAB),繪制直方圖組件ImageHist(MATLAB),均值濾波組件Avgfilter(C++)和椒鹽加噪組件AddSaltpeppernoise(Python)。然后按照實(shí)驗(yàn)流程連接組件,用戶可以更改流程圖中組件的名稱。調(diào)節(jié)椒鹽加噪組件的參數(shù)density和均值濾波組件的參數(shù)hsize。默認(rèn)density參數(shù)為0.5,hsize參數(shù)為2。

圖6 空間域圖像增強(qiáng)實(shí)驗(yàn)
圖7 展示了實(shí)驗(yàn)運(yùn)行路徑和結(jié)果,點(diǎn)擊實(shí)驗(yàn)結(jié)果圖片可以查看原圖。

圖7 空間域圖像增強(qiáng)實(shí)驗(yàn)結(jié)果
平臺(tái)采取分布式調(diào)度策略[12-14]完成對(duì)高并發(fā)實(shí)驗(yàn)的處理,系統(tǒng)可以根據(jù)需要設(shè)置多個(gè)調(diào)度服務(wù)器,平臺(tái)為管理員提供了實(shí)驗(yàn)調(diào)度監(jiān)控視圖,管理員可以看到整體調(diào)度集群的調(diào)度統(tǒng)計(jì)結(jié)果,并能選擇時(shí)間段直觀地查看實(shí)驗(yàn)運(yùn)行過(guò)程,包括實(shí)驗(yàn)的提交時(shí)間、運(yùn)行時(shí)間、結(jié)束時(shí)間和實(shí)驗(yàn)運(yùn)行狀態(tài)信息。
為了保證系統(tǒng)的高效可用,對(duì)其中一個(gè)調(diào)度服務(wù)器調(diào)度實(shí)驗(yàn)進(jìn)行了統(tǒng)計(jì)。測(cè)試實(shí)例中,處于waiting-Running待運(yùn)行狀態(tài)的實(shí)驗(yàn)有740個(gè),平均每個(gè)實(shí)驗(yàn)包含12個(gè)組件,實(shí)驗(yàn)的輸入圖片大小為500 KB,每個(gè)組件的運(yùn)行時(shí)間約為1 s,一個(gè)實(shí)驗(yàn)的運(yùn)行時(shí)間平均12 s,調(diào)度服務(wù)器CPU核數(shù)為8個(gè),內(nèi)存8 GB,設(shè)置線程池的最大值為20。對(duì)單個(gè)實(shí)驗(yàn)調(diào)度的開始和結(jié)束時(shí)間進(jìn)行了可視化統(tǒng)計(jì)展示,開始時(shí)間呈上升趨勢(shì),反映了調(diào)度服務(wù)器同步獲取數(shù)據(jù)存儲(chǔ)層的數(shù)據(jù),多線程并發(fā)異步運(yùn)行待運(yùn)行的實(shí)驗(yàn)。根據(jù)調(diào)度理想時(shí)間(min)計(jì)算公式得750個(gè)實(shí)驗(yàn)的理想運(yùn)行時(shí)間為7.4 min,得出實(shí)際實(shí)驗(yàn)調(diào)度間隔時(shí)間為8 min。中間同步獲取數(shù)據(jù)和算法服務(wù)器間通信的網(wǎng)絡(luò)傳輸代價(jià)是時(shí)間誤差的主要來(lái)源,屬于有效誤差。
本文設(shè)計(jì)的實(shí)驗(yàn)平臺(tái)非常靈活,除了數(shù)字圖像處理課程還可以用于其他算法設(shè)計(jì)類課程的實(shí)現(xiàn),如數(shù)字信號(hào)處理、密碼學(xué)、機(jī)器學(xué)習(xí)等。
總之,本文在解決了算法構(gòu)件化、跨編程語(yǔ)言調(diào)用和調(diào)度優(yōu)化等關(guān)鍵技術(shù)問(wèn)題的基礎(chǔ)上,設(shè)計(jì)并實(shí)現(xiàn)了一個(gè)能集成多種編程語(yǔ)言的實(shí)驗(yàn)平臺(tái),為數(shù)字圖像處理課程提供了完整的實(shí)驗(yàn)環(huán)境。