刁海洋
(西門子(中國)有限公司上海分公司,上海 200082)
工控安全態(tài)勢感知系統(tǒng)不僅關(guān)系著工廠內(nèi)設(shè)備和網(wǎng)絡(luò)的安全,對工廠的整體安全管理、決策控制都有著非常重要的影響。如何保證工控安全態(tài)勢感知系統(tǒng)及時有效地反映設(shè)備和網(wǎng)絡(luò)的安全狀態(tài),保證統(tǒng)計分析類的數(shù)據(jù)及時得到處理,這些問題在態(tài)勢感知類的系統(tǒng)中受到極大關(guān)注,如何對數(shù)據(jù)挖掘和分析的處理任務(wù)進行協(xié)調(diào)和調(diào)度成為必須解決的難題。時間輪算法的出現(xiàn)對于解決工控態(tài)勢安全感知系統(tǒng)中的關(guān)鍵問題有著非常重大的意義。
工控安全態(tài)勢感知系統(tǒng)問題通常涉及多個維度,但是其最根本問題是對數(shù)據(jù)的挖掘和分析任務(wù)進行有效的管理,包括定時任務(wù)的類別和數(shù)量、定時任務(wù)的協(xié)調(diào)和調(diào)度、定時任務(wù)的分布式管理等問題[1]。
工業(yè)安全環(huán)境下,有大量的設(shè)備數(shù)據(jù)和網(wǎng)絡(luò)流量需要被采集、存儲和分析,包括設(shè)備的基本信息、應(yīng)用數(shù)據(jù)、系統(tǒng)日志、協(xié)議解析日志、事件日志以及網(wǎng)絡(luò)的流量數(shù)據(jù)等,這些數(shù)據(jù)都需要被存儲到存儲引擎中。在工控安全態(tài)勢感知系統(tǒng)中,以Elastic Search作為原始數(shù)據(jù)存儲引擎[2],為安全審計和上層的業(yè)務(wù)邏輯處理提供服務(wù)。對于這些種類繁多的數(shù)據(jù),需要按照面向?qū)ο笤O(shè)計的思想,采用多種不同的定時任務(wù)進行處理。比如對于事件類型的日志,系統(tǒng)的事件種類也分多種,如嘗試連接事件、系統(tǒng)登錄事件等,對于不同的事件上層業(yè)務(wù)需求是不同的,那么就需要開發(fā)大量的定時任務(wù)進行業(yè)務(wù)邏輯處理,這就導(dǎo)致了在整個系統(tǒng)中定時任務(wù)的類別和數(shù)量較多。
在系統(tǒng)中,有些任務(wù)需要每隔一段時間執(zhí)行的,有些任務(wù)有前后依賴關(guān)系,有些任務(wù)需要在執(zhí)行一段時間之后根據(jù)業(yè)務(wù)邏輯判斷是否取消。雖然在Java官方提供的框架中,有一些專門用來處理定時任務(wù)協(xié)調(diào)的工具,比如Timer,Scheduled Executor Service,這些工具的調(diào)度時間復(fù)雜度為O(LogN)級別。當(dāng)包含著業(yè)務(wù)邏輯的定時任務(wù)類別和數(shù)量都很多時,這些工具的自身調(diào)度耗時將會影響到定時任務(wù)實際執(zhí)行的有效周期,進而會影響到任務(wù)本身。如何對這些任務(wù)進行高效的協(xié)調(diào)和調(diào)度非常關(guān)鍵。
為了保證服務(wù)的高可用性,工控安全態(tài)勢感知系統(tǒng)是以分布式的方式在工廠內(nèi)部署,各個服務(wù)是以多個服務(wù)器來均衡處理前端和數(shù)據(jù)計算層的服務(wù)請求,這些服務(wù)器以哈希的方式接收相應(yīng)的請求,執(zhí)行業(yè)務(wù)邏輯并返回結(jié)果。定時任務(wù)分散在各個服務(wù)器中,以特定的條件來觸發(fā)和執(zhí)行。那么,在分布式的環(huán)境下,如何保障這些大量的定時任務(wù)能夠定期有序地在服務(wù)器之間調(diào)度和執(zhí)行,不會重復(fù)和遺漏,是個重要的任務(wù)管理問題。
在定時任務(wù)體系架構(gòu)中,有多種調(diào)度框架和工具,比如前文提及的Timer,除此之外業(yè)界常見的還有時間輪、Quartz、Elastic-Job、XXL-JOB、Spring Task等[3]。在這些框架和工具中,有些在單機環(huán)境下以鏈表的方式按照執(zhí)行順序來存儲定時任務(wù),然后按照Native的wait方式執(zhí)行時間的流動和判斷,有些則是在分布式環(huán)境下以數(shù)據(jù)庫或者Zookeeper來協(xié)調(diào)分布式定時任務(wù)的執(zhí)行。單機環(huán)境下的定時任務(wù)調(diào)度工具側(cè)重于任務(wù)調(diào)度相關(guān)的效率和可靠性,在此基礎(chǔ)之上向使用者提供便捷的配置管理;分布式環(huán)境下的定時任務(wù)調(diào)度工具則更關(guān)注多個服務(wù)器之間如何同步定時任務(wù)的狀態(tài)信息,一般都是通過第三方組件來執(zhí)行狀態(tài)信息的管理。
以環(huán)形的隊列作為時間格(Timing Wheel),每個時間格上掛載著以雙向鏈表數(shù)據(jù)結(jié)構(gòu)存儲的任務(wù)列表,雙向鏈表中的每一個元素表示需要執(zhí)行的任務(wù)項,這些任務(wù)項的執(zhí)行時間一致,省去了任務(wù)調(diào)度器逐個判斷任務(wù)執(zhí)行時間的開銷。通過表盤指針指向當(dāng)前時間所在的位置,當(dāng)指針指向到某一個時間格時,則任務(wù)調(diào)度器就將該鏈表上的所有任務(wù)取出執(zhí)行。當(dāng)需要增加新的定時任務(wù)時,根據(jù)當(dāng)前指針位置和定時任務(wù)的時間偏移量,將該任務(wù)加入對應(yīng)的時間格的任務(wù)鏈表,通過尾部指針的指向?qū)⑷蝿?wù)添加到雙向鏈表的末端。同時以“時間格×?xí)r間跨度”作為當(dāng)前的時間輪的總時間跨度,當(dāng)某些任務(wù)的時間偏移量超過當(dāng)前時間輪的總時間跨度時,增加多層時間輪,通過時間輪之間的層次關(guān)系以及任務(wù)的升維和降維,來標(biāo)志系統(tǒng)中所有的待執(zhí)行定時任務(wù)。
從上述實現(xiàn)原理可以看出,任務(wù)的寫入和執(zhí)行的時間復(fù)雜度都是以O(shè)(1)為常數(shù)級。通過多層時間輪的方式進行時間的分層,以執(zhí)行的時間為單元對任務(wù)進行劃分,將任務(wù)按照所屬時間輪掛載到對應(yīng)位置。隨著時間的流轉(zhuǎn),多層時間輪上掛載的任務(wù)升級或者降級到對應(yīng)層級的時間輪位置,這種方式減少了任務(wù)的執(zhí)行時間和系統(tǒng)當(dāng)前時間的對比次數(shù)。除此之外,每個任務(wù)被固定以雙向鏈表的方式掛載在時間格中,當(dāng)需要對任務(wù)進行新增、刪除、修改和查詢時,在雙向鏈表這種數(shù)據(jù)結(jié)構(gòu)上,可以很方便地執(zhí)行相應(yīng)操作,減少調(diào)度指針前進和回溯的次數(shù)。最后,當(dāng)需要執(zhí)行任務(wù)的時候整條鏈表都會被執(zhí)行,省去了類似于Timer這些工具中的判斷時間。時間輪算法的低復(fù)雜度能夠顯著降低任務(wù)調(diào)度工具的時間開銷,提高調(diào)度效率,非常適合定時任務(wù)數(shù)量較多的場景。
圖1 基于時間輪算法的定時任務(wù)調(diào)度
業(yè)界主流的Kafka,Dubbo,ZooKeeper,Netty,Caffeine,Akka等框架都有時間輪算法的應(yīng)用。這些框架中有著較多的延時執(zhí)行操作,比如延時拉取、延時刪除、延時選舉、心跳檢測、超時處理等任務(wù),這些任務(wù)在大容量、高并發(fā)的場景下,對調(diào)度時間有著非常高的要求。比如Kafka單機環(huán)境下最大每秒能生產(chǎn)和消費百萬條消息,能夠同時支持2萬個客戶端同時連接,這種情況下需要處理的定時任務(wù)將會非常多,而這些任務(wù)都依賴于底層的定時任務(wù)調(diào)度器進行處理。時間輪算法能夠非常高效地協(xié)調(diào)和調(diào)度這些任務(wù),為框架應(yīng)用的持續(xù)高性能運行提供保障。
將時間輪算法應(yīng)用到工控安全態(tài)勢感知系統(tǒng)之中,對時間輪算法的邏輯進行二次開發(fā),根據(jù)業(yè)務(wù)的要求配置時間輪的間隔和輪數(shù),重新實現(xiàn)任務(wù)調(diào)度的邏輯,對特定的業(yè)務(wù)進行適當(dāng)?shù)亩ㄖ聘脑欤瑢r間輪算法與原有系統(tǒng)的業(yè)務(wù)以模塊化的方式組合在一起,類似于微服務(wù)的形式,對時間輪算法模塊的修改和發(fā)布不影響原有業(yè)務(wù)系統(tǒng)的正常運行。在實現(xiàn)二次開發(fā)和模塊化之后,任務(wù)調(diào)度模塊可以更好地協(xié)調(diào)和調(diào)度工控安全態(tài)勢感知系統(tǒng)中大量存在的統(tǒng)計分析定時任務(wù),除此之外將原先采用的Spring Task的Scheduled分散處理方式改為集中化管理,定時任務(wù)需要先向任務(wù)調(diào)度模塊注冊之后才能運行,最后將任務(wù)調(diào)度模塊的具體任務(wù)調(diào)度邏輯與Redis的分布式鎖結(jié)合在一起,通過引入第三方組件的方式解決分布式場景下定時任務(wù)的調(diào)度和執(zhí)行問題。
圖1描繪了引入時間輪算法之后任務(wù)調(diào)度模塊的設(shè)計,系統(tǒng)初始化時有3層時間輪,將每層時間輪設(shè)置為20格,以秒為基本單位,第一層時間輪的范圍為0~20 s,第二層時間輪的范圍為20~400 s,第三層時間輪的范圍為400~8 000 s。在運行過程中時間輪的層數(shù)根據(jù)任務(wù)的分配時間動態(tài)擴展,當(dāng)系統(tǒng)中需要調(diào)度的時間超過8 000 s,則會增加第四層時間輪,以此類推直至可配置的最大范圍。在每層對應(yīng)時間格上掛載相應(yīng)的定時任務(wù)雙向鏈表,每個鏈表上的任務(wù)都相應(yīng)加了Redis的分布式鎖,各個任務(wù)的鎖都不相同,以任務(wù)的唯一ID作為區(qū)分。在取出雙向鏈表的所有任務(wù)并調(diào)度到其中某一個時,調(diào)度模塊將該任務(wù)上的鎖與Redis中的鎖進行對比判斷是否執(zhí)行該任務(wù)。
在工控安全態(tài)勢感知系統(tǒng)中,由于原始數(shù)據(jù)存儲在Elastic Search存儲引擎中,上層業(yè)務(wù)需要使用大量的定時任務(wù)從原始數(shù)據(jù)中挖掘出業(yè)務(wù)需要的信息。原先的設(shè)計使用的是實時聚合和少量的定時任務(wù)挖掘來實現(xiàn)統(tǒng)計和分析型的業(yè)務(wù),這種方式導(dǎo)致了在數(shù)據(jù)量增長之后系統(tǒng)響應(yīng)時間變長。在引入時間輪算法之后,對統(tǒng)計分析型的任務(wù)進行拆解和分層。根據(jù)不同的業(yè)務(wù)類型,對系統(tǒng)事件、網(wǎng)絡(luò)流量、資產(chǎn)變化等不同的業(yè)務(wù)劃分多個類別,對于不同的類別再以時間的維度做進一步的分層。在整個統(tǒng)計分析任務(wù)分層過程中,以5秒鐘、分鐘、小時、天、周、月、季度或年為單位進行分層[4],將這個層級的概念下沉到時間輪算法的實現(xiàn)模塊中。由于每種類型的業(yè)務(wù)對應(yīng)不同的定時任務(wù),還需要再進行對應(yīng)時間的分層,那么整體定時任務(wù)的數(shù)量就會大幅增長,時間輪算法能夠非常好地處理大量的定時任務(wù),保證系統(tǒng)的穩(wěn)定運行。
在之前的設(shè)計中,采用的是Spring Task的Scheduled方式,在各個需要定時執(zhí)行的業(yè)務(wù)代碼的位置加上需要定時處理的注解,就會將調(diào)度的邏輯交給Spring框架來處理,這種方式非常簡單便捷,但是帶來了管理上的問題。引入時間輪算法之后,設(shè)計了獨立的模塊,各個需要執(zhí)行定時任務(wù)的位置都需要在該模塊中注冊,只有在注冊之后才能將定時任務(wù)交由時間輪來調(diào)度和執(zhí)行。在注冊的子模塊中,會對所有注冊了的定時任務(wù)進行權(quán)限的識別、行為的記錄,便于后續(xù)對定時任務(wù)的集中化管理,比如在界面上由管理員手工取消、重啟。在交由時間輪算法實現(xiàn)模塊集中化管理之后,之前隱藏在代碼邏輯中的定時任務(wù)完全交由該模塊來管理,任務(wù)的執(zhí)行和調(diào)度不再受制于業(yè)務(wù)模塊,整體設(shè)計上契合面向?qū)ο蠼怦畹乃枷搿?/p>
在工控安全態(tài)勢感知系統(tǒng)中,實際的部署場景包含分布式多機部署,后臺服務(wù)被同時部署到多臺服務(wù)器中以實現(xiàn)負(fù)載均衡,定時任務(wù)也就會被分散在各個服務(wù)器中。在之前的設(shè)計中,將定時任務(wù)集中部署在某一臺服務(wù)器單獨運行,如果該服務(wù)器宕機就會導(dǎo)致整體定時任務(wù)出現(xiàn)問題。而單獨的時間輪算法僅支持單機環(huán)境下的定時任務(wù)執(zhí)行,無法對分布式場景下的定時任務(wù)進行調(diào)度。在這種場景下,額外引入Redis分布式鎖的技術(shù)[5]。當(dāng)時間指針轉(zhuǎn)動到需要執(zhí)行定時任務(wù)的時間格時,需要先將該鏈表上所有任務(wù)取出來,逐個判斷該任務(wù)是否已經(jīng)在Redis中加上執(zhí)行鎖;如果已經(jīng)加上則在當(dāng)前服務(wù)器上放棄執(zhí)行,否則在Redis上加上新的執(zhí)行鎖,表明當(dāng)前已經(jīng)在執(zhí)行,其他服務(wù)器輪轉(zhuǎn)到該任務(wù)時,就會發(fā)現(xiàn)該任務(wù)正在被執(zhí)行而直接跳過。這樣,時間輪算法和Redis分布式鎖技術(shù)的結(jié)合可實現(xiàn)分布式場景下的定時任務(wù)調(diào)度。
本文對如何保證工控安全態(tài)勢感知系統(tǒng)中定時任務(wù)的高效率調(diào)度進行了分析和研究。在西門子工廠實際部署前后的對比研究表明,將時間輪算法應(yīng)用到工控安全態(tài)勢感知系統(tǒng)中,能夠有效提高系統(tǒng)的運行效率,保證任務(wù)持續(xù)穩(wěn)定地運行,為用戶提供了安全穩(wěn)定的使用環(huán)境。在工業(yè)互聯(lián)網(wǎng)環(huán)境下,工控安全態(tài)勢感知技術(shù)已成為工業(yè)安全應(yīng)用趨勢,時間輪算法發(fā)揮著重大的作用。