程 旭,張 斌,劉一田
(南瑞集團(tuán)有限公司(國網(wǎng)電力科學(xué)研究院有限公司),南京 210003)
在當(dāng)今信息化社會(huì)中,工作流程已得到廣泛和深入的使用[1].在傳統(tǒng)流程的建模過程中,流程開發(fā)者通過設(shè)計(jì)流程圖,構(gòu)建活動(dòng)節(jié)點(diǎn),來規(guī)劃流程的走向,實(shí)現(xiàn)流程的功能[2].雖然傳統(tǒng)的流程建模方便,易用性高,但是,當(dāng)流程非常復(fù)雜時(shí),流程圖中的活動(dòng)和遷移線也會(huì)錯(cuò)綜復(fù)雜,甚至還需要在流程腳本中實(shí)現(xiàn)相當(dāng)多的代碼,成倍增加設(shè)計(jì)的復(fù)雜度.
傳統(tǒng)流程流轉(zhuǎn)的本質(zhì)是通過代碼創(chuàng)建活動(dòng)實(shí)例和工作項(xiàng)等流程的基本狀態(tài)信息,而使用工作流狀態(tài)機(jī)開發(fā)流程,就是將其本質(zhì)抽象出來,通過狀態(tài)中的代碼控制流程的流轉(zhuǎn),省去繁雜的活動(dòng)和遷移線.將活動(dòng)節(jié)點(diǎn)抽象成狀態(tài),通過工作流狀態(tài)機(jī)實(shí)現(xiàn)狀態(tài)之間的遷移,可以對傳統(tǒng)流程中的活動(dòng)進(jìn)行簡化.云計(jì)算在業(yè)界早已具有成熟的應(yīng)用案例,工作流狀態(tài)機(jī)依托現(xiàn)有的云計(jì)算技術(shù),實(shí)現(xiàn)高性能、可擴(kuò)展的云狀態(tài)機(jī).
自工作流管理聯(lián)盟(WfMC)1993年成立以來,工作流技術(shù)已日趨成熟穩(wěn)定[3].業(yè)界提出了眾多流程規(guī)范,包括流程設(shè)計(jì)規(guī)范《業(yè)務(wù)流程模型和符號(hào)》2.0版本(BPMN 2.0)等[4],這些都為工作流產(chǎn)品提供了統(tǒng)一的標(biāo)準(zhǔn),當(dāng)前主流商業(yè)產(chǎn)品如IBM業(yè)務(wù)流程管理,開源產(chǎn)品如Activiti等均支持BPMN規(guī)范.通常流程引擎采用的核心調(diào)度算法包括有限狀態(tài)機(jī)(FSM)和基于令牌的Petri網(wǎng)(PetriNet)等.
自谷歌十年前提出云計(jì)算概念以來,云技術(shù)經(jīng)歷了長足的發(fā)展,目前已經(jīng)形成了通信即服務(wù)(CaaS)、基礎(chǔ)設(shè)施即服務(wù)(IaaS)、監(jiān)測即服務(wù)(MaaS)、平臺(tái)即服務(wù)(PaaS)和軟件即服務(wù)(SaaS)等多種基于互聯(lián)網(wǎng)的云計(jì)算服務(wù)[5].工作流結(jié)合云計(jì)算也已具有廣泛應(yīng)用,與傳統(tǒng)的工作流中間件相比,優(yōu)勢明顯:云工作流與應(yīng)用系統(tǒng)的架構(gòu)無關(guān);基于網(wǎng)絡(luò)協(xié)議的任何系統(tǒng)都可以消費(fèi)云工作流API;可以被獨(dú)立部署,支持分布式和集群;單一的云流程服務(wù)器可以滿足多個(gè)系統(tǒng)嵌入工作流的需要;使用云工作流易于大數(shù)據(jù)下的流程節(jié)點(diǎn)橫向擴(kuò)展.
微軟最早在 2005 年 Windows Workflow Foundation(WWF)產(chǎn)品中成功實(shí)踐了狀態(tài)機(jī)工作流的概念[6],其自身Activity機(jī)制能繪制出清晰的狀態(tài)圖.但是在復(fù)雜場景下,例如存在多次交互跳轉(zhuǎn)的情況下,其使用上仍然不如直接開發(fā)代碼簡潔易用.因此,本文基于有限狀態(tài)機(jī)的原理提出了云工作流狀態(tài)機(jī),不對流程邏輯代碼做出任何束縛,充分發(fā)揮代碼開發(fā)的優(yōu)勢,利用云環(huán)境下的特性,創(chuàng)建出高效、易用和可擴(kuò)展的工作流程.
工作流狀態(tài)機(jī)是有限狀態(tài)機(jī)的理論在業(yè)務(wù)流程中的應(yīng)用,將傳統(tǒng)流程中活動(dòng)的遷移表示為狀態(tài)之間的變換,以實(shí)現(xiàn)流程的流轉(zhuǎn).
有限狀態(tài)機(jī)有三個(gè)特征:狀態(tài)總數(shù)是有限的;任一時(shí)刻,只處在一種狀態(tài)之中;某種條件下,會(huì)從一種狀態(tài)轉(zhuǎn)變到另一種狀態(tài).工作流狀態(tài)機(jī)是一種有限狀態(tài)機(jī)[7],是表示有限多個(gè)狀態(tài)以及在這些狀態(tài)之間轉(zhuǎn)移和狀態(tài)內(nèi)動(dòng)作的數(shù)學(xué)模型.有限狀態(tài)機(jī)是五元組(Σ,S,s0,δ,F),其中,Σ是輸入字母表(符號(hào)的非空有限集合);S是狀態(tài)的非空有限集合;s0是初始狀態(tài),它是S的元素;δ是狀態(tài)轉(zhuǎn)移函數(shù):δ:S×Σ →S;F是最終狀態(tài)的集合,S的(可能為空)子集.
以工作流狀態(tài)機(jī)為用例,狀態(tài)機(jī)的狀態(tài)總數(shù)為S,其中啟動(dòng)流程的初始狀態(tài)為s0,進(jìn)入狀態(tài)時(shí)的輸入信息為 Σ,每一個(gè)狀態(tài)(即S中的每一個(gè)元素)內(nèi)部包含狀態(tài)轉(zhuǎn)移函數(shù) δ,輸出狀態(tài)為F.啟動(dòng)流程時(shí),外界輸入信息Σ到狀態(tài)s0,s0狀態(tài)調(diào)用內(nèi)部狀態(tài)轉(zhuǎn)移函數(shù) δ,生成下一步的狀態(tài)F;發(fā)送流程時(shí),將F作為本次狀態(tài)轉(zhuǎn)移的初始狀態(tài)s0,再進(jìn)行狀態(tài)遷移,生成下一步狀態(tài)F;結(jié)束流程時(shí),生成的下一步狀態(tài)F為空,不再進(jìn)行狀態(tài)轉(zhuǎn)移.可見,工作流狀態(tài)機(jī)的下一步狀態(tài)F是由當(dāng)前狀態(tài)s0中的狀態(tài)轉(zhuǎn)移函數(shù) δ和輸入信息 Σ共同決定的.
一個(gè)工作流狀態(tài)機(jī)由若干個(gè)狀態(tài)組成,每個(gè)狀態(tài)提供“進(jìn)入(Enter)”和“流轉(zhuǎn)(Resume)”方法.狀態(tài)機(jī)進(jìn)入某個(gè)狀態(tài)(如狀態(tài)1)后產(chǎn)生一個(gè)標(biāo)志(Bookmark),將標(biāo)志返回給調(diào)用者后就開始等待.直到外界再次通過標(biāo)志觸發(fā)流轉(zhuǎn)方法后,該狀態(tài)繼續(xù)流轉(zhuǎn),根據(jù)輸入值和流轉(zhuǎn)的內(nèi)部邏輯,決定下一個(gè)狀態(tài),并進(jìn)入到下一個(gè)狀態(tài)的進(jìn)入方法,執(zhí)行完畢會(huì)返回一個(gè)標(biāo)志并開始等待.如此循環(huán)直到狀態(tài)返回“結(jié)束”時(shí),工作流狀態(tài)機(jī)不再進(jìn)入新的狀態(tài),而是結(jié)束當(dāng)前狀態(tài)并結(jié)束狀態(tài)機(jī),實(shí)現(xiàn)流程的結(jié)束功能.其基本運(yùn)行模式如圖1所示.
圖1 工作流狀態(tài)機(jī)的基本運(yùn)行模式
工作流狀態(tài)機(jī)對外暴露“啟動(dòng)(Start)”、“流轉(zhuǎn)(Resume)”和“終止(Abort)”三個(gè)基本的方法.一個(gè)工作流狀態(tài)機(jī)相當(dāng)于一個(gè)流程實(shí)例,可以由外界通過這三個(gè)方法控制流程實(shí)例的流轉(zhuǎn).在所有的狀態(tài)之中必須具有一個(gè)開始狀態(tài),用于接受啟動(dòng)方法調(diào)用,當(dāng)執(zhí)行啟動(dòng)方法時(shí),工作流狀態(tài)機(jī)進(jìn)入到開始狀態(tài)的“進(jìn)入”方法,并返回標(biāo)志(Bookmark)將流程懸掛,等待下一次的調(diào)用.當(dāng)外界調(diào)用流轉(zhuǎn)方法時(shí),將標(biāo)志(Bookmark)傳入,根據(jù)當(dāng)前狀態(tài)的返回值決定并進(jìn)入下一個(gè)要進(jìn)入的狀態(tài).在終止方法被調(diào)用時(shí),系統(tǒng)自動(dòng)設(shè)置標(biāo)志(Bookmark)的狀態(tài)和工作流狀態(tài)機(jī)的狀態(tài)為失效,用于標(biāo)識(shí)流程的不可用狀態(tài).工作流狀態(tài)機(jī)通過每一個(gè)狀態(tài)的“流轉(zhuǎn)”方法返回的結(jié)果實(shí)現(xiàn)了不同狀態(tài)的多次跳轉(zhuǎn),輕松實(shí)現(xiàn)流程的追回、回退以及自由流的功能,從而脫離了原先通過遷移線固化流程運(yùn)行軌跡的流程設(shè)計(jì)方式,取而代之的是通過代碼操控流程的流向——這種流程設(shè)計(jì)的優(yōu)勢在于流程的設(shè)計(jì)更加靈活,不用局限于原有的活動(dòng)和遷移線的概念,當(dāng)流程運(yùn)行場景非常復(fù)雜時(shí),可通過代碼來簡化原先流程的活動(dòng)節(jié)點(diǎn).工作流狀態(tài)機(jī)的流轉(zhuǎn)機(jī)制如圖2所示.
圖2 工作流狀態(tài)機(jī)的流轉(zhuǎn)機(jī)制
流程通過狀態(tài)的返回結(jié)果來控制流程的流向,在流程正常流轉(zhuǎn)到下一個(gè)狀態(tài)的情況下,系統(tǒng)會(huì)將當(dāng)前的標(biāo)志(Bookmark)置為失效,并創(chuàng)建一個(gè)基于新狀態(tài)的標(biāo)志(Bookmark);當(dāng)狀態(tài)返回“結(jié)束”標(biāo)志時(shí),流程終結(jié),不再進(jìn)入后續(xù)狀態(tài),系統(tǒng)自動(dòng)結(jié)束當(dāng)前的工作流狀態(tài)機(jī)和標(biāo)志(Bookmark);當(dāng)狀態(tài)返回為當(dāng)前本身的狀態(tài)時(shí),即下一個(gè)狀態(tài)與當(dāng)前狀態(tài)相同,那么在重新進(jìn)入自身狀態(tài)執(zhí)行時(shí),當(dāng)前狀態(tài)的標(biāo)志(Bookmark)不失效,且不重新生成新的標(biāo)志(Bookmark),此種場景多用于活動(dòng)的多實(shí)例會(huì)簽.三種場景的比較如圖3所示.
圖3 工作流狀態(tài)機(jī)的三種狀態(tài)返回場景
結(jié)合云技術(shù)與工作流狀態(tài)機(jī)的原理,采用微服務(wù)化的架構(gòu)設(shè)計(jì)開發(fā).傳統(tǒng)的工作流服務(wù)是一個(gè)工作流引擎,可設(shè)計(jì)運(yùn)轉(zhuǎn)多個(gè)流程,而轉(zhuǎn)變?yōu)槲⒎?wù)的模式后,每一個(gè)流程就是一個(gè)服務(wù),可部署在容器中,從而實(shí)現(xiàn)流程服務(wù)的動(dòng)態(tài)伸縮,優(yōu)化利用資源.
當(dāng)前主流云架構(gòu)基本使用Docker容器技術(shù)搭建[8],工作流狀態(tài)機(jī)在開發(fā)完成后發(fā)布成鏡像,可啟動(dòng)多個(gè)該鏡像的Docker容器,技術(shù)上選用Spring Cloud解決方案[9],配合Eureka的服務(wù)發(fā)現(xiàn)機(jī)制和Zookeeper的分布式協(xié)調(diào)服務(wù)[10],實(shí)現(xiàn)微服務(wù)化的狀工作流狀態(tài)機(jī)集群.
通過Eureka的服務(wù)注冊發(fā)現(xiàn)機(jī)制實(shí)現(xiàn)負(fù)載均衡:每一個(gè)工作流狀態(tài)機(jī)啟動(dòng)時(shí)向Eureka服務(wù)注冊,客戶端調(diào)用映射出的服務(wù),Eureka會(huì)根據(jù)內(nèi)部算法將請求自動(dòng)轉(zhuǎn)發(fā)到任意一個(gè)狀態(tài)機(jī)容器中;通過Spring Cloud Config的中心化配置實(shí)現(xiàn)所有容器中配置信息的統(tǒng)一更新.在啟動(dòng)工作流時(shí),將狀態(tài)機(jī)ID與當(dāng)前節(jié)點(diǎn)信息自動(dòng)注冊到Zookeeper服務(wù)器中臨時(shí)性節(jié)點(diǎn),后續(xù)如果有任何與狀態(tài)機(jī)ID相關(guān)的操作全部轉(zhuǎn)發(fā)到此節(jié)點(diǎn)中執(zhí)行,這樣可保證一個(gè)流程只在一個(gè)節(jié)點(diǎn)中執(zhí)行,同一個(gè)流程的并發(fā)操作在流程控制器中排隊(duì)執(zhí)行.將狀態(tài)機(jī)的Docker容器加入統(tǒng)一的Swarm集群中,可實(shí)現(xiàn)狀態(tài)機(jī)之間的請求轉(zhuǎn)發(fā).數(shù)據(jù)庫存儲(chǔ)表結(jié)構(gòu)比較簡單,無需復(fù)雜的SQL查詢,因此選用高性能的文檔型數(shù)據(jù)庫MongoDB存儲(chǔ),提高插入與查詢的效率[11].微服務(wù)化的云架構(gòu)圖如圖4所示.
圖4 微服務(wù)化的云架構(gòu)圖
在云架構(gòu)下的每個(gè)工作流狀態(tài)機(jī)微服務(wù)都對外暴露Restful接口,它接收到請求后,通過分派器查找所請求的流程實(shí)例所在的微服務(wù)節(jié)點(diǎn),找到后將請求轉(zhuǎn)發(fā)到目標(biāo)服務(wù)所在節(jié)點(diǎn),目標(biāo)節(jié)點(diǎn)收到請求后由控制器實(shí)際處理.流程開發(fā)者繼承狀態(tài)機(jī)和狀態(tài)兩個(gè)基類,開發(fā)與具體業(yè)務(wù)相關(guān)的流程狀態(tài)機(jī)和流程狀態(tài).控制器中實(shí)現(xiàn)了流程狀態(tài)的跳轉(zhuǎn),每一個(gè)狀態(tài)都存在“進(jìn)入”和“流轉(zhuǎn)”兩個(gè)方法.在“進(jìn)入”方法中,通過進(jìn)入上下文創(chuàng)建標(biāo)識(shí)和工作項(xiàng),在“流轉(zhuǎn)”方法中,返回下一個(gè)狀態(tài)的名稱.同時(shí),還可以設(shè)置狀態(tài)機(jī)和狀態(tài)的變量,由數(shù)據(jù)訪問層將狀態(tài)機(jī)以及變量數(shù)據(jù)、標(biāo)識(shí)數(shù)據(jù)和工作項(xiàng)保存如MongoDB數(shù)據(jù)庫中.云工作流狀態(tài)機(jī)系統(tǒng)結(jié)構(gòu)圖如圖5所示.
每一個(gè)工作流產(chǎn)生的流程實(shí)例固定運(yùn)行在某一個(gè)微服務(wù)節(jié)點(diǎn)上,所有請求由該節(jié)點(diǎn)中的控制器處理.控制器中的工作原理是一個(gè)單線程池,所有與當(dāng)前流程實(shí)例相關(guān)的操作排隊(duì)進(jìn)入到控制器中的單線程池中,一個(gè)操作處理完畢后再處理下一個(gè)操作,這樣在處理兩個(gè)同樣的請求時(shí),能夠保證只處理一次,在第一次操作處理完畢后,數(shù)據(jù)的狀態(tài)已經(jīng)發(fā)生變化,就無法處理第二次請求.簡言之,通過單線程的排隊(duì)處理規(guī)避了正常情況下使用鎖的機(jī)制,以此減少了創(chuàng)建鎖和銷毀鎖的開銷,大幅提升了狀態(tài)機(jī)流轉(zhuǎn)效率.控制器中通過原子變量累計(jì)請求次數(shù),當(dāng)控制器中現(xiàn)有多個(gè)請求完成后,即請求次數(shù)與完成次數(shù)相等時(shí),工作流服務(wù)卸載當(dāng)前的控制器.
圖5 云工作流狀態(tài)機(jī)系統(tǒng)結(jié)構(gòu)圖
云工作流狀態(tài)機(jī)基于Spring Cloud技術(shù)提供了云環(huán)境下的不同狀態(tài)之間的遷移功能[12],從底層保證了狀態(tài)之間流轉(zhuǎn)的穩(wěn)定和高效.業(yè)務(wù)系統(tǒng)基于狀態(tài)機(jī)研發(fā)工作流時(shí)不用考慮底層狀態(tài)流轉(zhuǎn)的性能與并發(fā)問題,只需要編寫每一個(gè)狀態(tài)的進(jìn)入(Enter)和流轉(zhuǎn)(Resume)方法,根據(jù)需要生成工作項(xiàng),并開發(fā)客戶端,即可實(shí)現(xiàn)一個(gè)業(yè)務(wù)流程.除此之外,云狀態(tài)機(jī)不提供統(tǒng)一的流程圖和流程日志,業(yè)務(wù)研發(fā)人員根據(jù)需要自行定制流程圖,記錄流程日志.
雖然與傳統(tǒng)的工作流只需要在界面上拖拽流程元素的開發(fā)方式相比,編寫代碼要復(fù)雜一些,但遇到極為復(fù)雜的流程時(shí),使用狀態(tài)機(jī)的狀態(tài)來代替?zhèn)鹘y(tǒng)流程中的活動(dòng)能夠大幅簡化流程圖的復(fù)雜度.將多個(gè)順序或分支活動(dòng)融合為一個(gè)狀態(tài),在狀態(tài)內(nèi)部通過代碼邏輯代替遷移線的判斷邏輯,執(zhí)行后續(xù)狀態(tài)遷移.
實(shí)驗(yàn)分別對傳統(tǒng)工作流程和云工作流狀態(tài)機(jī)進(jìn)行壓力測試,通過比對分析測試結(jié)果而得出結(jié)論.兩者的測試環(huán)境相同,硬件環(huán)境為多臺(tái)8核16 GB內(nèi)存的IBM x3650 服務(wù)器,操作系統(tǒng)為 Linux 6.5.傳統(tǒng)工作流程的中間件為Weblogic 11,采用雙機(jī)集群的方式部署在兩臺(tái)服務(wù)器上,數(shù)據(jù)庫為 Oracle 11g,獨(dú)立部署在另外一臺(tái)服務(wù)器上.云狀態(tài)機(jī)在兩臺(tái)服務(wù)器上各啟動(dòng)一個(gè)Docker容器,加入到國家電網(wǎng)公司智能運(yùn)檢分析管控系統(tǒng)的測試Swarm集群中,Eureka、Zookeeper和Mongodb均采用Swarm集群中已經(jīng)配置完成的節(jié)點(diǎn).使用LoadRunner 11編寫兩個(gè)腳本進(jìn)行壓測[13],每個(gè)測試腳本均以簡單的報(bào)銷審批流程為例,傳統(tǒng)流程包含一個(gè)開始填單活動(dòng)和3個(gè)人工活動(dòng),云狀態(tài)機(jī)包含一個(gè)開始填單狀態(tài)和一個(gè)審批狀態(tài),在審批狀態(tài)中會(huì)產(chǎn)生3次工作項(xiàng).每個(gè)壓測腳本執(zhí)行一次啟動(dòng),4次發(fā)送操作,將一個(gè)流程發(fā)送到結(jié)束.
測試時(shí)使用100并發(fā)壓力,執(zhí)行時(shí)間30分鐘.兩者事務(wù)通過率都為100%,測試結(jié)果有效,將4次發(fā)送耗時(shí)取平均值統(tǒng)計(jì)如表1.
表1 傳統(tǒng)工作流程與云工作流性能測試結(jié)果對比
統(tǒng)計(jì)結(jié)果表明,100并發(fā)時(shí)云狀態(tài)機(jī)單次請求的平均響應(yīng)時(shí)間約在20 ms左右,遠(yuǎn)低于傳統(tǒng)工作流引擎的響應(yīng)耗時(shí).可見,云工作流狀態(tài)機(jī)內(nèi)部的系統(tǒng)架構(gòu)設(shè)計(jì)以及非關(guān)系型數(shù)據(jù)庫的構(gòu)建行之有效,保證了流程運(yùn)行時(shí)的高性能.實(shí)際生產(chǎn)環(huán)境中當(dāng)訪問壓力較大時(shí),通過啟動(dòng)多個(gè)Docker容器分散壓力,減少請求響應(yīng)時(shí)間;當(dāng)訪問量較小時(shí),可以關(guān)閉 Docker容器,節(jié)約系統(tǒng)資源,從而實(shí)現(xiàn)微服務(wù)的彈性伸縮[14].
本文設(shè)計(jì)并實(shí)現(xiàn)了微服務(wù)化的云工作流狀態(tài)機(jī),文中闡述了系統(tǒng)的關(guān)鍵技術(shù)與核心架構(gòu),實(shí)驗(yàn)結(jié)果表明其性能優(yōu)于傳統(tǒng)流程.云工作流狀態(tài)機(jī)屬于國家電網(wǎng)公司網(wǎng)省版智能運(yùn)檢分析管控系統(tǒng)中可擴(kuò)展框架平臺(tái)的一部分,支撐了運(yùn)檢指令等業(yè)務(wù)流程的開發(fā),得到了廣泛應(yīng)用.使用工作流狀態(tài)機(jī)開發(fā)業(yè)務(wù)流程對流程開發(fā)人員的水平要求較高,在進(jìn)行流程設(shè)計(jì)前,需要深度了解業(yè)務(wù)需求,規(guī)劃出若干合理的工作流狀態(tài).后續(xù)需要解決的一個(gè)問題是,由于云狀態(tài)機(jī)的性能過高,導(dǎo)致壓力轉(zhuǎn)移到Zookeeper上,引起了單節(jié)點(diǎn)Zookeeper的不穩(wěn)定.另外,要針對業(yè)務(wù)需求提供更加豐富的接口,并研究通用的流程圖與流程日志,減輕業(yè)務(wù)開發(fā)壓力.