程 旭,張 斌,劉一田
(南瑞集團有限公司(國網電力科學研究院有限公司),南京 210003)
在當今信息化社會中,工作流程已得到廣泛和深入的使用[1].在傳統流程的建模過程中,流程開發者通過設計流程圖,構建活動節點,來規劃流程的走向,實現流程的功能[2].雖然傳統的流程建模方便,易用性高,但是,當流程非常復雜時,流程圖中的活動和遷移線也會錯綜復雜,甚至還需要在流程腳本中實現相當多的代碼,成倍增加設計的復雜度.
傳統流程流轉的本質是通過代碼創建活動實例和工作項等流程的基本狀態信息,而使用工作流狀態機開發流程,就是將其本質抽象出來,通過狀態中的代碼控制流程的流轉,省去繁雜的活動和遷移線.將活動節點抽象成狀態,通過工作流狀態機實現狀態之間的遷移,可以對傳統流程中的活動進行簡化.云計算在業界早已具有成熟的應用案例,工作流狀態機依托現有的云計算技術,實現高性能、可擴展的云狀態機.
自工作流管理聯盟(WfMC)1993年成立以來,工作流技術已日趨成熟穩定[3].業界提出了眾多流程規范,包括流程設計規范《業務流程模型和符號》2.0版本(BPMN 2.0)等[4],這些都為工作流產品提供了統一的標準,當前主流商業產品如IBM業務流程管理,開源產品如Activiti等均支持BPMN規范.通常流程引擎采用的核心調度算法包括有限狀態機(FSM)和基于令牌的Petri網(PetriNet)等.
自谷歌十年前提出云計算概念以來,云技術經歷了長足的發展,目前已經形成了通信即服務(CaaS)、基礎設施即服務(IaaS)、監測即服務(MaaS)、平臺即服務(PaaS)和軟件即服務(SaaS)等多種基于互聯網的云計算服務[5].工作流結合云計算也已具有廣泛應用,與傳統的工作流中間件相比,優勢明顯:云工作流與應用系統的架構無關;基于網絡協議的任何系統都可以消費云工作流API;可以被獨立部署,支持分布式和集群;單一的云流程服務器可以滿足多個系統嵌入工作流的需要;使用云工作流易于大數據下的流程節點橫向擴展.
微軟最早在 2005 年 Windows Workflow Foundation(WWF)產品中成功實踐了狀態機工作流的概念[6],其自身Activity機制能繪制出清晰的狀態圖.但是在復雜場景下,例如存在多次交互跳轉的情況下,其使用上仍然不如直接開發代碼簡潔易用.因此,本文基于有限狀態機的原理提出了云工作流狀態機,不對流程邏輯代碼做出任何束縛,充分發揮代碼開發的優勢,利用云環境下的特性,創建出高效、易用和可擴展的工作流程.
工作流狀態機是有限狀態機的理論在業務流程中的應用,將傳統流程中活動的遷移表示為狀態之間的變換,以實現流程的流轉.
有限狀態機有三個特征:狀態總數是有限的;任一時刻,只處在一種狀態之中;某種條件下,會從一種狀態轉變到另一種狀態.工作流狀態機是一種有限狀態機[7],是表示有限多個狀態以及在這些狀態之間轉移和狀態內動作的數學模型.有限狀態機是五元組(Σ,S,s0,δ,F),其中,Σ是輸入字母表(符號的非空有限集合);S是狀態的非空有限集合;s0是初始狀態,它是S的元素;δ是狀態轉移函數:δ:S×Σ →S;F是最終狀態的集合,S的(可能為空)子集.
以工作流狀態機為用例,狀態機的狀態總數為S,其中啟動流程的初始狀態為s0,進入狀態時的輸入信息為 Σ,每一個狀態(即S中的每一個元素)內部包含狀態轉移函數 δ,輸出狀態為F.啟動流程時,外界輸入信息Σ到狀態s0,s0狀態調用內部狀態轉移函數 δ,生成下一步的狀態F;發送流程時,將F作為本次狀態轉移的初始狀態s0,再進行狀態遷移,生成下一步狀態F;結束流程時,生成的下一步狀態F為空,不再進行狀態轉移.可見,工作流狀態機的下一步狀態F是由當前狀態s0中的狀態轉移函數 δ和輸入信息 Σ共同決定的.
一個工作流狀態機由若干個狀態組成,每個狀態提供“進入(Enter)”和“流轉(Resume)”方法.狀態機進入某個狀態(如狀態1)后產生一個標志(Bookmark),將標志返回給調用者后就開始等待.直到外界再次通過標志觸發流轉方法后,該狀態繼續流轉,根據輸入值和流轉的內部邏輯,決定下一個狀態,并進入到下一個狀態的進入方法,執行完畢會返回一個標志并開始等待.如此循環直到狀態返回“結束”時,工作流狀態機不再進入新的狀態,而是結束當前狀態并結束狀態機,實現流程的結束功能.其基本運行模式如圖1所示.

圖1 工作流狀態機的基本運行模式
工作流狀態機對外暴露“啟動(Start)”、“流轉(Resume)”和“終止(Abort)”三個基本的方法.一個工作流狀態機相當于一個流程實例,可以由外界通過這三個方法控制流程實例的流轉.在所有的狀態之中必須具有一個開始狀態,用于接受啟動方法調用,當執行啟動方法時,工作流狀態機進入到開始狀態的“進入”方法,并返回標志(Bookmark)將流程懸掛,等待下一次的調用.當外界調用流轉方法時,將標志(Bookmark)傳入,根據當前狀態的返回值決定并進入下一個要進入的狀態.在終止方法被調用時,系統自動設置標志(Bookmark)的狀態和工作流狀態機的狀態為失效,用于標識流程的不可用狀態.工作流狀態機通過每一個狀態的“流轉”方法返回的結果實現了不同狀態的多次跳轉,輕松實現流程的追回、回退以及自由流的功能,從而脫離了原先通過遷移線固化流程運行軌跡的流程設計方式,取而代之的是通過代碼操控流程的流向——這種流程設計的優勢在于流程的設計更加靈活,不用局限于原有的活動和遷移線的概念,當流程運行場景非常復雜時,可通過代碼來簡化原先流程的活動節點.工作流狀態機的流轉機制如圖2所示.

圖2 工作流狀態機的流轉機制
流程通過狀態的返回結果來控制流程的流向,在流程正常流轉到下一個狀態的情況下,系統會將當前的標志(Bookmark)置為失效,并創建一個基于新狀態的標志(Bookmark);當狀態返回“結束”標志時,流程終結,不再進入后續狀態,系統自動結束當前的工作流狀態機和標志(Bookmark);當狀態返回為當前本身的狀態時,即下一個狀態與當前狀態相同,那么在重新進入自身狀態執行時,當前狀態的標志(Bookmark)不失效,且不重新生成新的標志(Bookmark),此種場景多用于活動的多實例會簽.三種場景的比較如圖3所示.

圖3 工作流狀態機的三種狀態返回場景
結合云技術與工作流狀態機的原理,采用微服務化的架構設計開發.傳統的工作流服務是一個工作流引擎,可設計運轉多個流程,而轉變為微服務的模式后,每一個流程就是一個服務,可部署在容器中,從而實現流程服務的動態伸縮,優化利用資源.
當前主流云架構基本使用Docker容器技術搭建[8],工作流狀態機在開發完成后發布成鏡像,可啟動多個該鏡像的Docker容器,技術上選用Spring Cloud解決方案[9],配合Eureka的服務發現機制和Zookeeper的分布式協調服務[10],實現微服務化的狀工作流狀態機集群.
通過Eureka的服務注冊發現機制實現負載均衡:每一個工作流狀態機啟動時向Eureka服務注冊,客戶端調用映射出的服務,Eureka會根據內部算法將請求自動轉發到任意一個狀態機容器中;通過Spring Cloud Config的中心化配置實現所有容器中配置信息的統一更新.在啟動工作流時,將狀態機ID與當前節點信息自動注冊到Zookeeper服務器中臨時性節點,后續如果有任何與狀態機ID相關的操作全部轉發到此節點中執行,這樣可保證一個流程只在一個節點中執行,同一個流程的并發操作在流程控制器中排隊執行.將狀態機的Docker容器加入統一的Swarm集群中,可實現狀態機之間的請求轉發.數據庫存儲表結構比較簡單,無需復雜的SQL查詢,因此選用高性能的文檔型數據庫MongoDB存儲,提高插入與查詢的效率[11].微服務化的云架構圖如圖4所示.

圖4 微服務化的云架構圖
在云架構下的每個工作流狀態機微服務都對外暴露Restful接口,它接收到請求后,通過分派器查找所請求的流程實例所在的微服務節點,找到后將請求轉發到目標服務所在節點,目標節點收到請求后由控制器實際處理.流程開發者繼承狀態機和狀態兩個基類,開發與具體業務相關的流程狀態機和流程狀態.控制器中實現了流程狀態的跳轉,每一個狀態都存在“進入”和“流轉”兩個方法.在“進入”方法中,通過進入上下文創建標識和工作項,在“流轉”方法中,返回下一個狀態的名稱.同時,還可以設置狀態機和狀態的變量,由數據訪問層將狀態機以及變量數據、標識數據和工作項保存如MongoDB數據庫中.云工作流狀態機系統結構圖如圖5所示.
每一個工作流產生的流程實例固定運行在某一個微服務節點上,所有請求由該節點中的控制器處理.控制器中的工作原理是一個單線程池,所有與當前流程實例相關的操作排隊進入到控制器中的單線程池中,一個操作處理完畢后再處理下一個操作,這樣在處理兩個同樣的請求時,能夠保證只處理一次,在第一次操作處理完畢后,數據的狀態已經發生變化,就無法處理第二次請求.簡言之,通過單線程的排隊處理規避了正常情況下使用鎖的機制,以此減少了創建鎖和銷毀鎖的開銷,大幅提升了狀態機流轉效率.控制器中通過原子變量累計請求次數,當控制器中現有多個請求完成后,即請求次數與完成次數相等時,工作流服務卸載當前的控制器.

圖5 云工作流狀態機系統結構圖
云工作流狀態機基于Spring Cloud技術提供了云環境下的不同狀態之間的遷移功能[12],從底層保證了狀態之間流轉的穩定和高效.業務系統基于狀態機研發工作流時不用考慮底層狀態流轉的性能與并發問題,只需要編寫每一個狀態的進入(Enter)和流轉(Resume)方法,根據需要生成工作項,并開發客戶端,即可實現一個業務流程.除此之外,云狀態機不提供統一的流程圖和流程日志,業務研發人員根據需要自行定制流程圖,記錄流程日志.
雖然與傳統的工作流只需要在界面上拖拽流程元素的開發方式相比,編寫代碼要復雜一些,但遇到極為復雜的流程時,使用狀態機的狀態來代替傳統流程中的活動能夠大幅簡化流程圖的復雜度.將多個順序或分支活動融合為一個狀態,在狀態內部通過代碼邏輯代替遷移線的判斷邏輯,執行后續狀態遷移.
實驗分別對傳統工作流程和云工作流狀態機進行壓力測試,通過比對分析測試結果而得出結論.兩者的測試環境相同,硬件環境為多臺8核16 GB內存的IBM x3650 服務器,操作系統為 Linux 6.5.傳統工作流程的中間件為Weblogic 11,采用雙機集群的方式部署在兩臺服務器上,數據庫為 Oracle 11g,獨立部署在另外一臺服務器上.云狀態機在兩臺服務器上各啟動一個Docker容器,加入到國家電網公司智能運檢分析管控系統的測試Swarm集群中,Eureka、Zookeeper和Mongodb均采用Swarm集群中已經配置完成的節點.使用LoadRunner 11編寫兩個腳本進行壓測[13],每個測試腳本均以簡單的報銷審批流程為例,傳統流程包含一個開始填單活動和3個人工活動,云狀態機包含一個開始填單狀態和一個審批狀態,在審批狀態中會產生3次工作項.每個壓測腳本執行一次啟動,4次發送操作,將一個流程發送到結束.
測試時使用100并發壓力,執行時間30分鐘.兩者事務通過率都為100%,測試結果有效,將4次發送耗時取平均值統計如表1.

表1 傳統工作流程與云工作流性能測試結果對比
統計結果表明,100并發時云狀態機單次請求的平均響應時間約在20 ms左右,遠低于傳統工作流引擎的響應耗時.可見,云工作流狀態機內部的系統架構設計以及非關系型數據庫的構建行之有效,保證了流程運行時的高性能.實際生產環境中當訪問壓力較大時,通過啟動多個Docker容器分散壓力,減少請求響應時間;當訪問量較小時,可以關閉 Docker容器,節約系統資源,從而實現微服務的彈性伸縮[14].
本文設計并實現了微服務化的云工作流狀態機,文中闡述了系統的關鍵技術與核心架構,實驗結果表明其性能優于傳統流程.云工作流狀態機屬于國家電網公司網省版智能運檢分析管控系統中可擴展框架平臺的一部分,支撐了運檢指令等業務流程的開發,得到了廣泛應用.使用工作流狀態機開發業務流程對流程開發人員的水平要求較高,在進行流程設計前,需要深度了解業務需求,規劃出若干合理的工作流狀態.后續需要解決的一個問題是,由于云狀態機的性能過高,導致壓力轉移到Zookeeper上,引起了單節點Zookeeper的不穩定.另外,要針對業務需求提供更加豐富的接口,并研究通用的流程圖與流程日志,減輕業務開發壓力.