流程引擎的架構設計

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 流程引擎的組成單元

  1. 組織、角色、用戶、成員的組織架構託管;

  2. 流程資源文件的配置、校驗、存儲和執行,對不同的流程節點,流程引擎自動結合配置、數據處理其對應的業務邏輯,流程數據自動處理;

  3. 表單配置、數據綁定,表單數據的根據流程配置自動處理;

  4. 通用的數據接口;

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 流程項目實踐流程

  1. 確定組織架構

  2. 確定流程,包括流程佈局、審批人設置、權限

  3. 確定表單信息(字段、類型、數據源、校驗規則)和表單樣式

  4. 確定頁面佈局、樣式、數據字段、搜索、導入、導出

  5. 報表

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
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 >
<startEvent activiti:initiator="employeeName">
<extensionElements>
<activiti:formProperty />
<activiti:formProperty  />
<activiti:formProperty  />
</extensionElements>
</startEvent>
<sequenceFlow sourceRef="request" targetRef="handleRequest" />
<userTask  >
<documentation>
${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).
</documentation>
<extensionElements>
<activiti:formProperty >
<activiti:value  />
<activiti:value  />
</activiti:formProperty>
<activiti:formProperty  />
</extensionElements>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow sourceRef="handleRequest" targetRef="requestApprovedDecision" />
<exclusiveGateway name="Request approved?" />
<sequenceFlow sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression>
</sequenceFlow>
<task  />
<sequenceFlow sourceRef="sendApprovalMail" targetRef="theEnd1" />
<endEvent />
<sequenceFlow sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}</conditionExpression>
</sequenceFlow>
<userTask >
<documentation>
Your manager has disapproved your vacation request for ${numberOfDays} days.
Reason: ${managerMotivation}
</documentation>
<extensionElements>
<activiti:formProperty ${numberOfDays}" type="long" required="true"/>
<activiti:formProperty ${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
<activiti:formProperty ${vacationMotivation}" type="string" />
<activiti:formProperty name="Resend vacation request to manager?" type="enum" required="true">
<activiti:value  />
<activiti:value  />
</activiti:formProperty>
</extensionElements>
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>${employeeName}</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
</userTask>
<sequenceFlow sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" />
<exclusiveGateway name="Resend request?" />
<sequenceFlow sourceRef="resendRequestDecision" targetRef="handleRequest">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="resendRequestDecision" targetRef="theEnd2">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}</conditionExpression>
</sequenceFlow>
<endEvent />
</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 業務識別

  1. 識別業務場景中的配置項,使用集合或分組的方式,讓業務可配置

  2. 支撐業務流程過程的可配置化

  3. 支撐業務場景中的數據,自動處理

3.4.2 流程引擎的實現

  1. 資源相關服務,資源加載,資源保存,資源加密等

  2. 配置項相關服務

  3. PVM 虛擬機的實現,即通過某個節點(發起時爲開始節點)作爲初始節點,按照某個連線的 action 進行節點的自動執行的虛擬機

  4. 數據配置、數據權限

  5. 流程數據和業務數據的自動處理

4 商業機會

  1. Business Process Analysis (BPA) 流程分析,幫助企業進行流程調整和優化

  2. Process Assets Library(PAL)流程資產庫,對企業流程進行知識化沉澱,將制度和流程落地做綁定,讓審批人知曉流程中對應的職責

  3. Process Simulate 流程模擬,自動化測試

  4. Process Forecast 流程預測

  5. 低代碼平臺

  6. 更廣泛的機會,在於業務領域 + 流程引擎,比如:DevOps、RPA、應用與服務編排、數據編排、FaaS 編排等。

作者:京東雲開發者 - 馬瑞

來源:https://my.oschina.net/u/4090830/blog/5584471

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/SK1TSEOBya9sdnb1if7xEg