流程引擎的架構設計
1 什麼是流程引擎
流程引擎是一個底層支撐平臺,是為提供流程處理而開發設計的。流程引擎和流程應用,以及應用程式的關係如下圖所示。
常見的支撐場景有:Workflow、BPM、流程編排等。本次分享,主要從BPM流程引擎切入,介紹流程引擎的架構設計方法。
1.1 什麼是流程
簡單來說,流程就是一系列活動的組合。比如,用於企業辦公的OA系統中,就存在大量的申請審批類的流程。在生產製造業,有大量的從銷售端的訂單,到生產製造,再到簽收回款的生產銷售流程。在機器學習領域,有亞馬遜AWS Sagemaker的大資料處理、機器學習的應用。綜上,流程是一個概念,在和具體實現結合時,就產生了不同的流程產品,如DevOps、Spring Data Stream等。
在流程實現方面,主要可以分為2種實現方式,一種是用程式碼實現,比如:用程式碼實現一個加班申請,那麼就要自己對接SSO進行單點登入,透過介面拿到發起人和審批人的資訊,同時儲存表單資料。另一種方式是使用流程引擎來實現,流程引擎對接應用場景所需資料,如加班申請,流程引擎對接SSO、OU、審批人配置、許可權等,實現這樣一個流程,只需要關心流程配置、流程節點和流程表單即可,流程流轉以及流程的資料處理,都透過流程引擎來完成。
流程引擎可以快速落地流程實現,這也是流程引擎存在的價值。
1.2 什麼是引擎
一般而言,引擎是一個程式或一套系統的支援部分。常見的程式引擎有遊戲引擎、搜尋引擎、防毒引擎等。引擎是脫離具體業務場景的某一類業務場景的高度抽象和封裝。
比如,某OA公司,封裝了一套審批用的workflow,實施人員只需要配置流程和表單即可交付專案。再比如,美國某公司做了一個AI引擎做NBA(Next Best Action)推薦,封裝了推薦領域的常用演算法,在不同的場景自動選擇和組合多種演算法,進行智慧推薦。
1.3 流程設計器
流程設計器是流程和引擎的連線方,使用者透過流程設計器,將某種layout和rule固化成某種流程,然後透過資料和資料上下文,使用流程引擎自動按照某種固化的流程進行執行。
我將目前見到的流程設計器的理論基礎,分為以下三類:1,自定義系;2,UML中的活動圖系;3,BPMN系。
1.3.1 自定義系
用於Sagemaker等場景的AWS Step Function(自定義流程節點)
1.3.2 UML Activity Diagram
Flowportal BPM的流程設計器
1.3.3 BPMN系
activiti的流程設計器
炎黃盈動的流程設計器
題外話:炎黃盈動的流程設計器,和processon中的流程設計器介面幾乎一樣,因為本質上是一家的。
2 流程引擎的應用
2.1 Workflow
工作流管理聯盟(Workflow Management Coalition,WfMC)作為工作流管理的標準化組織而成立。
WfMC對工作流給出定義為:工作流是指一類能夠完全自動執行的經營過程,根據一系列過程規則,將文件、資訊或任務在不同的執行者之間進行傳遞與執行。
在workflow中,流程引擎主要用於支撐流程審批和資料流轉,應用場景非常廣泛。
國外產品(開源或商用)通常需求和操作比較簡單,不會有國內的需求那麼複雜。國內的產品,經歷了眾多客戶的錘鍊,功能目前都比較強大。
一般而言,workflow使用場景最多的是OA產品。在OA辦公中,包含了企業辦公中的大量元素,這些元素足夠形成特定的產品,比如門戶系統、移動辦公。在OA的專案落地過程中,結合行業、業務側重點又可以形成行業解決方案和專題方案。
以下是某OA公司產品和解決方案。
2.2 BPM(Business Process Management)
Workflow主要是解決審批和資料流轉,而BPM主要是解決端到端、資訊孤島等問題而存在的。大多數用BPM產品的客戶,都是在BPM基礎上進行系統搭建,比如在BPM上面搭建OA、CRM、HR等系統。
BPM的使用場景,比Workflow更廣泛,BPM產品中包含大量的和第三方系統互動的元件和自定義SQL、程式碼元件。比如,BPM系統中的檔案觸發器,可以在海關等互動場景下,透過監控FTP伺服器中的檔案,自動觸發流程例項;可以透過定時器Timer,自動每日執行資料同步,並透過Mail節點將同步結果通知到相關運營成員等。
BPM的應用,可以按照執行前、執行中和執行後來劃分。
2.3 流程編排
流程編排是脫離流程業務領域的更高一層抽象,使用方可以透過流程編排系統,結合自己的業務場景進行業務定製。比如,可以將相關業務程式碼,封裝成function,然後透過雲廠商平臺的FAAS平臺,將不同業務的function進行關聯和排程,從而完成某項任務。
3 流程引擎的架構設計
鑑於一些朋友可能沒有使用和接觸過流程引擎,先介紹流程引擎的組成單元,再介紹基於某個BPM產品的專案是如何進行開發的。我們透過BPM專案開發,對流程引擎的作用有個初步的認識。
3.1 BPM流程引擎的組成單元
- 組織、角色、使用者、成員的組織架構託管;
- 流程資原始檔的配置、校驗、儲存和執行,對不同的流程節點,流程引擎自動結合配置、資料處理其對應的業務邏輯,流程資料自動處理;
- 表單配置、資料繫結,表單資料的根據流程配置自動處理;
- 通用的資料介面;
3.1.1 組織架構的設計
3.1.2 流程設計器
流程設計器包含左側的分組節點列表,和右側的畫布。左側的節點可以如下進行設計。
問題:對於一個XML或JSON格式的流程圖,如何進行解析?
不同的節點,按照不同的業務場景,配置不同的配置項。比如,對於Human Node需要配置審批人,配置審批環節的展示表單,審批環節能夠修改哪些欄位,哪些欄位的修改要進行留痕等。
3.1.3 表單設計器
這種是按照表單相關資料表,生成出一個表單,然後對錶單欄位進行配置和資料繫結。
這種是Drag&Drop控制元件,然後配置控制元件的屬性,如繫結欄位等。
這種是Drag&Drop控制元件,無需關聯資料庫表欄位的表單
資料表生成表單的概要流程如下圖所示。
拖拽控制元件繫結資料表欄位的概要流程如下。
拖拽控制元件無需繫結資料表欄位的概要流程。使用NoSQL的Document記錄或使用RDS提供的JSON型別進行儲存會比較方便。
3.1.4 介面設計
結合Activity的介面設計,如下圖所示
一些系統在建立一個流程任務的時候,要先按照流程模板先建立一個應用示例,再關聯發起人和備註,呼叫RuntimeService,執行到StartNode,這類設計因人而異,這麼做略顯繁瑣。
3.2 基於流程引擎的專案開發實踐
3.2.1 流程專案實踐流程
- 確定組織架構
- 確定流程,包括流程佈局、審批人設定、許可權
- 確定表單資訊(欄位、型別、資料來源、校驗規則)和表單樣式
- 確定頁面佈局、樣式、資料欄位、搜尋、匯入、匯出
- 報表
3.2.2 組織架構
組織架構實現,有兩種方法,一種是按照維度進行資料管理,另一種是在同一棵組織架構樹下進行管理。
按照集團、公司、部門、使用者等不同維度,進行資料管理,比較常見,這裡不做討論。下圖為按維度維護資料的示例。
按照同一棵組織架構樹進行資料維護,介面一般顯示為左樹右表。大多數商業化產品,都會將此組織架構樹進行記憶體快取,以方便審批人查詢、開窗選擇OrgUnit、Role、User、Member等場景。Member的引入是為了解決一人多職等場景。一般發起流程的時候,需要帶出發起人擁有的Member列表,從而後續節點取合適的審批人。
對於組織架構而言,需要考慮,系統本身要具備OU儲存的能力,對於沒有組織架構的使用者,可以直接在系統的組織架構中新建組織架構。同時,對於已有系統的客戶,可以透過組織架構資料同步來進行資料自動維護。對於用AD域內部管控的客戶來說,需要具備AD域身份認證的能力。對於複雜場景,比如使用者是SaaS化等複雜場景,組織架構也需要在系統內部,支援使用API的方式來獲取組織資訊。
所以在組織架構設計的時候,要使用外掛的方式來做,具體使用哪種外掛,可以在配置檔案中進行配置。以下為一個商業產品的組織架構操作介面示例。
常見的組織架構操作還有組織架構同步,比如流程系統同步微信企業號、釘釘等,這裡不再展開。
3.2.3 流程設計
我們想象的流程,可能是向下面的這種簡單流程。
而實際專案,碰到的流程,一般是如下圖所示的情景。
初步看幾個流程的模型檔案是什麼樣的,先有個印象。
<?xml version="1.0" encoding="UTF-8" ?><definitions id="definitions"
targetNamespace="http://activiti.org/bpmn20"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn">
<process id="vacationRequest" name="Vacation request">
<startEvent id="request" activiti:initiator="employeeName">
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" type="long" value="1" required="true"/>
<activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
<activiti:formProperty id="vacationMotivation" name="Motivation" type="string" />
</extensionElements>
</startEvent>
<sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" />
<userTask id="handleRequest" name="Handle vacation request" >
<documentation>
${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}). </documentation>
<extensionElements>
<activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true">
<activiti:value id="true" name="Approve" />
<activiti:value id="false" name="Reject" />
</activiti:formProperty>
<activiti:formProperty id="managerMotivation" name="Motivation" type="string" />
</extensionElements>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow2" sourceRef="handleRequest" targetRef="requestApprovedDecision" />
<exclusiveGateway id="requestApprovedDecision" name="Request approved?" />
<sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression>
</sequenceFlow>
<task id="sendApprovalMail" name="Send confirmation e-mail" />
<sequenceFlow id="flow4" sourceRef="sendApprovalMail" targetRef="theEnd1" />
<endEvent id="theEnd1" />
<sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}</conditionExpression>
</sequenceFlow>
<userTask id="adjustVacationRequestTask" name="Adjust vacation request">
<documentation>
Your manager has disapproved your vacation request for ${numberOfDays} days.
Reason: ${managerMotivation} </documentation>
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/>
<activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
<activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" />
<activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true">
<activiti:value id="true" name="Yes" />
<activiti:value id="false" name="No" />
</activiti:formProperty>
</extensionElements>
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>${employeeName}</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
</userTask>
<sequenceFlow id="flow6" sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" />
<exclusiveGateway id="resendRequestDecision" name="Resend request?" />
<sequenceFlow id="flow7" sourceRef="resendRequestDecision" targetRef="handleRequest">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow8" sourceRef="resendRequestDecision" targetRef="theEnd2">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}</conditionExpression>
</sequenceFlow>
<endEvent id="theEnd2" />
</process></definitions>
一個螢幕截圖都截不完的流程,如果用程式碼去實現整個流程,其工作量和效率,可想而知。而實際做專案,使用基於流程引擎的產品來做專案的時候,只需要確定節點、節點配置、資料配置和許可權即可。
問題:一般流程,都帶有郵件通知的節點,如何實現郵件通知節點?請考慮以下情景。
流程流轉和執行的時候,會遇到各種情況的錯誤,比如找不到審批人等,此時流程引擎要對資料做rollback,而郵件通知節點的業務邏輯已經執行過了。
許可權方面,對於流程資源,哪些部門可以申請,哪些角色不可申請,都應該做流程控制。而在流程執行過程中,流程資料、不是路程的相關人也都不應該看到流程,處理過流程的審批人,不可以再對流程進行處理等,都是許可權方面要考慮的問題。
3.2.4 表單設計
如下圖所示的表單,可以分析以下,一個流程表單有多個主表資訊和多個子表資訊。一般而言,如果是透過流程引擎做非流程的資料處理,子表透過主表ID來做關聯,如果透過流程引擎做流程的資料處理,子表和主表透過TaskId來做關聯。以下為示例。
流程系統需要表單設計器,一個流程的不同節點可以掛接不同的表單,以方便不同角色的人關注不同維度的流程資訊
3.2.5 頁面設計
一般而言,對於流程的發起、審批、歷史記錄等,都是通用的系統介面。而一些業務場景,需要單獨做列表介面,以方便使用。對於已有門戶系統的客戶,需要融合其介面樣式。以下為曾經做過的專案示例。
3.2.6 報表
由於不是所有客戶都有報表系統,所以流程系統需要具備一個基本的報表功能。下圖為示例。
有報表系統的客戶,可以使用其商業版報表系統,獲取(直接取、數倉)資料進行展示。常見的報表系統有FineReport、Tableau、PowerBI等。
3.3 BPM流程引擎架構設計
3.3.1 流程引擎的架構設計
3.3.2 發起流程
流程引擎處理過程
執行節點處理過程
問題:在流程引擎處理過程中,如果一個節點有多條連線,如何尋找FromNodeId是某個Node的連線?
人工處理時,指定連線text
3.4 流程引擎架構設計
3.4.1 業務識別
識別業務場景中的配置項,使用集合或分組的方式,讓業務可配置
支撐業務流程過程的可配置化
支撐業務場景中的資料,自動處理
3.4.2 流程引擎的實現
資源相關服務,資源載入,資源儲存,資源加密等
配置項相關服務
PVM虛擬機器的實現,即透過某個節點(發起時為開始節點)作為初始節點,按照某個連線的action進行節點的自動執行的虛擬機器
資料配置、資料許可權
流程資料和業務資料的自動處理
4 商業機會
Business Process Analysis (BPA) 流程分析,幫助企業進行流程調整和最佳化
Process Assets Library(PAL)流程資產庫,對企業流程進行知識化沉澱,將制度和流程落地做繫結,讓審批人知曉流程中對應的職責
Process Simulate 流程模擬,自動化測試
Process Forecast 流程預測
低程式碼平臺
更廣泛的機會,在於業務領域+流程引擎,比如:DevOps、RPA、應用與服務編排、資料編排、FaaS編排等。
作者:馬瑞
相關文章
- 【推理引擎】ONNXRuntime 的架構設計2022-03-29架構
- 工作流引擎架構設計2023-01-12架構
- Twitter推薦引擎架構設計分析2024-03-05架構
- java 流程引擎 表單設計器 設計方案2021-11-16Java
- 架構設計之架構的演變2024-06-15架構
- 架構設計思想-微服務架構設計模式2020-06-24架構微服務設計模式
- 常用的設計架構2024-06-19架構
- 架構設計:服務自動化部署和管理流程2020-11-25架構
- SaaS架構:流程架構分析2024-09-20架構
- 初探Tomcat的架構設計2019-11-25Tomcat架構
- 架構設計的本質2020-10-10架構
- UI架構設計的演化2019-05-11UI架構
- 理解Underscore的設計架構2019-02-18架構
- 架構設計之一——基礎架構2022-05-02架構
- 架構師修煉之道(二)——架構?設計?架構師?2019-07-22架構
- 網易考拉規則引擎平臺架構設計與實踐2018-10-29架構
- 應用架構圖的設計2023-12-19應用架構
- 前端架構設計的方法論2018-11-01前端架構
- SaaS架構:開放平臺架構設計2024-10-12架構
- 遊戲架構 遊戲架構設計(8)2018-07-16遊戲架構
- 架構設計(九):估算2022-12-25架構
- 架構設計方法論2021-04-14架構
- 面向架構程式設計2020-12-12架構程式設計
- 網站架構設計2019-03-07網站架構
- 架構設計方法初探2018-06-22架構
- 大道至簡的架構設計思想之:封裝(C系架構設計法,sishuok)2023-03-02架構封裝
- 架構 規則引擎 quartz2019-02-27架構quartz
- Opensearch架構及引擎原理2018-03-22架構
- 架構設計 | 非同步處理流程,多種實現模式詳解2020-06-04架構非同步模式
- mPaaS 服務端核心元件:訊息推送 MPS 架構及流程設計2019-02-13服務端元件架構
- 【架構設計的藝術】Kafka如何通過精妙的架構設計優化JVM GC問題?【石杉的架構筆記】2019-05-06架構Kafka優化JVMGC筆記
- SaaS架構:中央庫存系統架構設計2024-10-14架構
- SaaS架構:多租戶系統架構設計2024-10-11架構
- 什麼是真正的架構設計?2020-03-24架構
- 面向演算法的架構設計2018-10-25演算法架構
- 架構設計中的基本原則2018-07-18架構
- 馳騁工作流引擎-父子流程設計說明2019-05-29
- 架構設計案例專題2024-03-27架構