舒新峰, 張 文, 王夢楠
(西安郵電大學 計算機學院,西安 710121)
編程能力是信息類專業(yè)學生的一個基本技能,掌握的好壞程度對后期專業(yè)課程的學習和就業(yè)具有重要的影響[1]。程序設計類課程擔負著編程能力訓練的重任,但是傳統(tǒng)紙質(zhì)作業(yè)和卷面考試的課程考核方式需要老師人工評判。一方面,任務繁重且評判效率低下;另一方面,導致了學生“重理論,輕實踐”,極大地影響了后期課程的學習[2]。如何用計算機技術解決學生編程能力的培養(yǎng)問題成為計算機實踐教學改革的一個研究重點[3]。
對于程序評測系統(tǒng)的研究,可以追溯到1965年Forsythe和Wirth提出的自動評分程序[4]。如今,國內(nèi)外已經(jīng)出現(xiàn)了很多在線程序評測系統(tǒng),如美國計算機奧林匹克競賽系統(tǒng)(USA Computing Olympiad,USACO)、北京大學在線評測系統(tǒng)(Peking University Online Judge,POJ)和浙江大學在線評測系統(tǒng)(Zhejiang University Online Judge,ZOJ)[5-7]。現(xiàn)有的評測系統(tǒng)一般為瀏覽器/服務器模式(Browser/Server,B/S)架構,學生通過Web頁面提交針對特定題目的解決方案,評測系統(tǒng)在判定服務器的操作系統(tǒng)上對學生提交的源程序進行編譯、運行及判定[8]。在線程序評測系統(tǒng)應用于計算機輔助教學中能給教學雙方都帶來極大的方便。一方面,激發(fā)學生編程的興趣,隨時進行編程學習;另一方面,教學人員節(jié)省閱讀學生代碼的時間,降低勞動強度。為防止學生代碼影響到判定服務器的安全性,例如盜取數(shù)據(jù)資源或破壞文件系統(tǒng),現(xiàn)有評測系統(tǒng)屏蔽了文件操作、多線程使用等重要的系統(tǒng)調(diào)用,不能很好的滿足程序設計類課程的判定需要[9-10]。
為解決上述問題,本文將Docker虛擬化技術引入到在線程序評測系統(tǒng)的判定引擎核心組件中,利用Docker的沙箱機制實現(xiàn)待測程序隔離于判定服務器的運行,確保了判定服務器的安全。同時,使用了分布式判定處理大規(guī)模高并發(fā)程序判定任務,提高程序評測系統(tǒng)的評測效率。最終設計實現(xiàn)了基于Docker容器的分布式程序判定系統(tǒng)(Docker Based Distributed Program Judgment System,DOJ)。
Docker是一個開源的應用容器引擎,它以Docker容器為資源分割和調(diào)度的基本單位,封裝整個軟件運行時環(huán)境,用于構建、發(fā)布和運行分布式應用的平臺[11-13],模塊結(jié)構如圖1所示。

圖1 Docker的模塊結(jié)構
Docker容器的隔離性主要通過namespace 分別將各容器的進程、網(wǎng)絡空間、文件系統(tǒng)和用戶隔離開[14]。不同用戶的進程通過pid namespace 隔離開,借此實現(xiàn)各容器中的進程互不影響。Docker容器通過Cgroup和Ulimit機制限定CPU、內(nèi)存等關鍵資源的使用,防止某個容器過度使用資源[15]。同時,從容器組網(wǎng)、鏡像簽名、監(jiān)控和文件系統(tǒng)級防護等方面進行全方位的容器安全保護。
DOJ系統(tǒng)定位為一個獨立于答題系統(tǒng)的程序判定軟件,總體架構如圖2所示,系統(tǒng)采用分布式架構,由任務調(diào)度器、程序判定引擎和監(jiān)控中心三部分構成,其中程序判定引擎的數(shù)量可以根據(jù)待判定任務的多少進行動態(tài)的擴縮。任務調(diào)度器負責接收來自于答題系統(tǒng)的程序判定任務,并進一步轉(zhuǎn)發(fā)給程序判定引擎進行判定;判定引擎對分配的程序基于Docker容器進行運行判定;監(jiān)控中心以可視化模式展示DOJ的運行狀況。

圖2 DOJ總體構架
DOJ各組件間采用可擴展標記語言(Extensible Markup Language,XML)數(shù)據(jù)格式傳輸數(shù)據(jù)。本系統(tǒng)設計了DOJ與答題系統(tǒng)間的外部交換數(shù)據(jù)格式(External data exchange format,EDEF)和組件間的內(nèi)部交換數(shù)據(jù)格式(Internal data exchange format,IDEF)兩種類型。EDEF的 XML數(shù)據(jù)格式如表1所示。由于篇幅有限,本文省略了部分輔助信息。同理,IDEF在EDEF的基礎上新增程序判定引擎IP和剩余數(shù)量等數(shù)據(jù)標簽。
任務調(diào)度器在DOJ中起著連接答題系統(tǒng)與程序判定引擎的重要橋梁作用,其詳細設計如圖3所示。任務調(diào)度器由判定引擎注冊模塊、任務接收模塊、任務分配模塊、結(jié)果處理模塊和監(jiān)控反饋模塊組成。
判定引擎注冊模塊負責維護注冊的判定引擎的基本狀態(tài),及時處理新注冊的判定引擎和長時間得不到回應的判定引擎。任務接收模塊接收答題系統(tǒng)提交的待判定任務,加入任務隊列。任務分配模塊根據(jù)判定引擎負載情況使用平滑的加權輪詢算法將讀取任務隊列的待判定任務發(fā)送至不同的判定引擎。
當一個程序判定引擎啟動時,需攜帶自己的地址、端口等信息向任務調(diào)度器申請注冊后,才能接收任務調(diào)度器發(fā)送的待判定任務。當任務調(diào)度器有待判定任務時就可以向這個地址發(fā)送待判定任務。若一臺程序判定引擎需要停止時,必須向任務調(diào)度器申請注銷,任務注冊模塊就會從程序判定引擎隊列中刪除此引擎。

表1 外部數(shù)據(jù)交換格式(EDEF)

圖3 任務調(diào)度器設計
任務調(diào)度器在接收到待判定任務后,將任務加入任務隊列。任務分配模塊讀取任務隊列,并修改已讀取任務的狀態(tài)為正在判定,通過平滑的加權輪詢算法發(fā)送至選定的程序判定引擎。程序判定引擎判題結(jié)束后將結(jié)果發(fā)送回任務調(diào)度器的結(jié)果處理模塊,由任務調(diào)度器將判題結(jié)果反饋給答題系統(tǒng)。
當任務隊列中某次任務的狀態(tài)長時間處于正在判定,DOJ會對此次任務進行重新判定。同時,用戶可以通過監(jiān)控中心來查看判定引擎的狀態(tài)及判定統(tǒng)計信息,及時發(fā)現(xiàn)并處理問題。
程序判定引擎是DOJ的核心組成部分,其設計及Docker運行模塊和結(jié)果判定流程如圖4所示。程序判定引擎由任務接收模塊、預處理模塊、編譯模塊、Docker運行模塊、結(jié)果判定模塊和發(fā)送結(jié)果模塊組成。預處理模塊的職責是解析XML文件并且配置判定環(huán)境;運行模塊負責運行目標程序,保存運行結(jié)果;結(jié)果判定模塊判定運行結(jié)果是否符合預期結(jié)果。

圖4 程序判定引擎設計及判定流程
當程序判定引擎收到待判定任務后,預處理模塊對任務進行解析,然后編譯模塊開始編譯,若編譯失敗,直接將結(jié)果保存到結(jié)果發(fā)送模塊,由此模塊將結(jié)果返回到任務調(diào)度器;若編譯成功,編譯之后,創(chuàng)建子進程啟動Docker容器,父進程等待執(zhí)行結(jié)果。在啟動的容器中,主進程創(chuàng)建新的子進程執(zhí)行用戶代碼,主進程通過讀取子進程信息文件”/proc/子進程PID”,獲取子進程運行的實時狀態(tài)。若用例全部通過則正常結(jié)束,反之異常結(jié)束。
結(jié)果判定模塊根據(jù)運行的結(jié)束狀態(tài)的異常與否決定是否對運行結(jié)果的正確性進行判斷。當運行異常結(jié)束時,結(jié)果判定模塊生成判定結(jié)果信息,判定結(jié)束;反之,對比各組用例執(zhí)行結(jié)果與預期結(jié)果是否相同得出判定結(jié)果。判定結(jié)束后經(jīng)過結(jié)果發(fā)送模塊將判定結(jié)果返回到任務調(diào)度器中。
本系統(tǒng)的運行環(huán)境要求64位Linux操作系統(tǒng),內(nèi)核版本在3.8及以上。實驗使用了4臺物理服務器,硬件配置為1核i5 CPU、8GB內(nèi)存、100MB帶寬,操作系統(tǒng)為ubuntu14.04。任務調(diào)度器與監(jiān)控中心部署在一臺服務器上,其他3臺服務器各自獨立運行一個判定引擎。系統(tǒng)啟動后,從監(jiān)控中心監(jiān)測到的DOJ物理服務器統(tǒng)計如圖5所示。

圖5 DOJ的物理服務器統(tǒng)計
本實驗題目來源于北京大學在線評測系統(tǒng)編號分別為DNA排序(1007)、堆排序(2388)和滑動窗口(2823)的3道題目,且增加了具體文件操作,多線程操作。對每道題目準備了多組測試用例,用來驗證用戶提交代碼的正確性。使用這些題目在西安郵電大學15級軟件工程專業(yè)組織了一次編程測試,收集到學生102份有效的C語言代碼。將學生提交的102份代碼經(jīng)DOJ判定后通過監(jiān)控中心得到如圖6所示的監(jiān)控結(jié)果。




圖6 程序判定引擎監(jiān)控結(jié)果
通過監(jiān)控中心,可以清晰的看到DOJ當前的判題情況,從統(tǒng)計角度可以看到判題數(shù)量、判題時間和各個判定引擎的詳細信息。
通過上述實驗,驗證了系統(tǒng)對文件操作、負載均衡等基本功能的支持。系統(tǒng)完成對任務的負載均衡,判定結(jié)果與預期結(jié)果一致。
“基于Docker容器的分布式程序判定系統(tǒng)”的獨立性和安全機制避免了答題系統(tǒng)提交的代碼對宿主機造成潛在的危險。有效的解決了在程序判定系統(tǒng)中進行文件操作、多線程的使用等問題。使用了分布式調(diào)度處理方式,可以實現(xiàn)任務的負載均衡,提高了系統(tǒng)的處理效率,很好的解決多任務量時的判定等待,緩解系統(tǒng)高負荷運行等情況。總之,既保證了安全、快速、準確的程序判定,又擴展了程序判定系統(tǒng)的應用范圍。
參考文獻(References):
[1] 何文廣, 周 珂, 熊剛強. 程序設計課程實驗教學改革與實踐[J]. 實驗室研究與探索, 2016, 35(6):163-165.
[2] 劉 毓,賈沛沛,劉傳明. 現(xiàn)代互聯(lián)網(wǎng)教學評價信息管理系統(tǒng)設計與實現(xiàn)[J]. 西安郵電大學學報,2015,20(1):119-124.
[3] 劉在英, 楊 平, 張麗曉. 程序設計課程實踐教學模式的探討[J]. 實驗室研究與探索, 2013, 32(10):156-159.
[4] Forsythe GE, Wirth N. Automatic grading programs[M]. Stanford University, 1965.
[5] Kolstad R, Piele D. USA computing olympiad(USACO)[J].Olympiads in Informatics, 2007(1):105-111.
[6] 李文新,郭 煒. 北京大學程序在線評測系統(tǒng)及其應用[J]. 吉林大學學報(信息科學版),2005(S2):170-177.
[7] 張浩斌. 基于開放式云平臺的開源在線評測系統(tǒng)設計與實現(xiàn)[J]. 計算機科學,2012,39(S3):339-343.
[8] 尤 楓, 史晟輝, 趙瑞蓮. 編譯程序在線評測系統(tǒng)的實現(xiàn)[J]. 實驗室研究與探索, 2010, 29(12):69-72.
[9] 陳 鵬. 在線評判系統(tǒng)的設計和實現(xiàn)[D]. 南京:東南大學,2015.
[10] 黃洪波. 大規(guī)模編程題在線評判技術研究[D]. 廣州:華南農(nóng)業(yè)大學,2016.
[11] 浙江大學SEL實驗室. Docker 容器與容器云[M].北京:人民郵電出版社, 2015.
[12] 張 怡. 基于Docker的虛擬化應用平臺設計與實[D]. 廣州:華南理工大學, 2016.
[13] 楊保華,戴王劍,曹亞侖.Docker技術入門與實戰(zhàn)(第2版)[M].北京:機械工業(yè)出版社, 2017:3-9.
[14] Franti?ekRadomír Sohlich, Tomá? Dulík.Docker as platform for assignments evaluation [J]. Procedia Engineering, 2015(100):1665-1671.
[15] 劉思堯,李 強,李 斌. 基于Docker技術的容器隔離性研究[J]. 軟件, 2015, 36(4):110-113.