流程引擎的架構(gòu)設(shè)計(jì)
點(diǎn)擊關(guān)注公眾號(hào):互聯(lián)網(wǎng)架構(gòu)師,后臺(tái)回復(fù) 2T獲取2TB學(xué)習(xí)資源!
上一篇:Alibaba開(kāi)源內(nèi)網(wǎng)高并發(fā)編程手冊(cè).pdf
1 什么是流程引擎
流程引擎是一個(gè)底層支撐平臺(tái),是為提供流程處理而開(kāi)發(fā)設(shè)計(jì)的。流程引擎和流程應(yīng)用,以及應(yīng)用程序的關(guān)系如下圖所示。

常見(jiàn)的支撐場(chǎng)景有:Workflow、BPM、流程編排等。本次分享,主要從 BPM 流程引擎切入,介紹流程引擎的架構(gòu)設(shè)計(jì)方法。
1.1 什么是流程
在流程實(shí)現(xiàn)方面,主要可以分為 2 種實(shí)現(xiàn)方式,一種是用代碼實(shí)現(xiàn),比如:用代碼實(shí)現(xiàn)一個(gè)加班申請(qǐng),那么就要自己對(duì)接 SSO 進(jìn)行單點(diǎn)登錄,通過(guò)接口拿到發(fā)起人和審批人的信息,同時(shí)保存表單數(shù)據(jù)。另一種方式是使用流程引擎來(lái)實(shí)現(xiàn),流程引擎對(duì)接應(yīng)用場(chǎng)景所需數(shù)據(jù),如加班申請(qǐng),流程引擎對(duì)接 SSO、OU、審批人配置、權(quán)限等,實(shí)現(xiàn)這樣一個(gè)流程,只需要關(guān)心流程配置、流程節(jié)點(diǎn)和流程表單即可,流程流轉(zhuǎn)以及流程的數(shù)據(jù)處理,都通過(guò)流程引擎來(lái)完成。
流程引擎可以快速落地流程實(shí)現(xiàn),這也是流程引擎存在的價(jià)值。
1.2 什么是引擎
一般而言,引擎是一個(gè)程序或一套系統(tǒng)的支持部分。常見(jiàn)的程序引擎有游戲引擎、搜索引擎、殺毒引擎等。引擎是脫離具體業(yè)務(wù)場(chǎng)景的某一類(lèi)業(yè)務(wù)場(chǎng)景的高度抽象和封裝。
比如,某 OA 公司,封裝了一套審批用的 workflow,實(shí)施人員只需要配置流程和表單即可交付項(xiàng)目。再比如,美國(guó)某公司做了一個(gè) AI 引擎做 NBA(Next Best Action)推薦,封裝了推薦領(lǐng)域的常用算法,在不同的場(chǎng)景自動(dòng)選擇和組合多種算法,進(jìn)行智能推薦。
1.3 流程設(shè)計(jì)器
流程設(shè)計(jì)器是流程和引擎的連接方,用戶通過(guò)流程設(shè)計(jì)器,將某種 layout 和 rule 固化成某種流程,然后通過(guò)數(shù)據(jù)和數(shù)據(jù)上下文,使用流程引擎自動(dòng)按照某種固化的流程進(jìn)行執(zhí)行。
我將目前見(jiàn)到的流程設(shè)計(jì)器的理論基礎(chǔ),分為以下三類(lèi):1,自定義系;2,UML 中的活動(dòng)圖系;3,BPMN 系。
1.3.1 自定義系
用于 Sagemaker 等場(chǎng)景的 AWS Step Function(自定義流程節(jié)點(diǎn))

1.3.2 UML Activity Diagram
Flowportal BPM 的流程設(shè)計(jì)器

1.3.3 BPMN 系
activiti 的流程設(shè)計(jì)器

炎黃盈動(dòng)的流程設(shè)計(jì)器

題外話:炎黃盈動(dòng)的流程設(shè)計(jì)器,和 processon 中的流程設(shè)計(jì)器界面幾乎一樣,因?yàn)楸举|(zhì)上是一家的。
2 流程引擎的應(yīng)用
2.1 Workflow

在 workflow 中,流程引擎主要用于支撐流程審批和數(shù)據(jù)流轉(zhuǎn),應(yīng)用場(chǎng)景非常廣泛。
國(guó)外產(chǎn)品(開(kāi)源或商用)通常需求和操作比較簡(jiǎn)單,不會(huì)有國(guó)內(nèi)的需求那么復(fù)雜。國(guó)內(nèi)的產(chǎn)品,經(jīng)歷了眾多客戶的錘煉,功能目前都比較強(qiáng)大。
一般而言,workflow 使用場(chǎng)景最多的是 OA 產(chǎn)品。在 OA 辦公中,包含了企業(yè)辦公中的大量元素,這些元素足夠形成特定的產(chǎn)品,比如門(mén)戶系統(tǒng)、移動(dòng)辦公。在 OA 的項(xiàng)目落地過(guò)程中,結(jié)合行業(yè)、業(yè)務(wù)側(cè)重點(diǎn)又可以形成行業(yè)解決方案和專題方案。
以下是某 OA 公司產(chǎn)品和解決方案。

2.2 BPM(Business Process Management)
Workflow 主要是解決審批和數(shù)據(jù)流轉(zhuǎn),而 BPM 主要是解決端到端、信息孤島等問(wèn)題而存在的。大多數(shù)用 BPM 產(chǎn)品的客戶,都是在 BPM 基礎(chǔ)上進(jìn)行系統(tǒng)搭建,比如在 BPM 上面搭建 OA、CRM、HR 等系統(tǒng)。
BPM 的使用場(chǎng)景,比 Workflow 更廣泛,BPM 產(chǎn)品中包含大量的和第三方系統(tǒng)交互的組件和自定義 SQL、代碼組件。比如,BPM 系統(tǒng)中的文件觸發(fā)器,可以在海關(guān)等交互場(chǎng)景下,通過(guò)監(jiān)控 FTP 服務(wù)器中的文件,自動(dòng)觸發(fā)流程實(shí)例;可以通過(guò)定時(shí)器 Timer,自動(dòng)每日?qǐng)?zhí)行數(shù)據(jù)同步,并通過(guò) Mail 節(jié)點(diǎn)將同步結(jié)果通知到相關(guān)運(yùn)營(yíng)成員等。


BPM 的應(yīng)用,可以按照?qǐng)?zhí)行前、執(zhí)行中和執(zhí)行后來(lái)劃分。

2.3 流程編排
流程編排是脫離流程業(yè)務(wù)領(lǐng)域的更高一層抽象,使用方可以通過(guò)流程編排系統(tǒng),結(jié)合自己的業(yè)務(wù)場(chǎng)景進(jìn)行業(yè)務(wù)定制。比如,可以將相關(guān)業(yè)務(wù)代碼,封裝成 function,然后通過(guò)云廠商平臺(tái)的 FAAS 平臺(tái),將不同業(yè)務(wù)的 function 進(jìn)行關(guān)聯(lián)和調(diào)度,從而完成某項(xiàng)任務(wù)。
3 流程引擎的架構(gòu)設(shè)計(jì)
鑒于一些朋友可能沒(méi)有使用和接觸過(guò)流程引擎,先介紹流程引擎的組成單元,再介紹基于某個(gè) BPM 產(chǎn)品的項(xiàng)目是如何進(jìn)行開(kāi)發(fā)的。我們通過(guò) BPM 項(xiàng)目開(kāi)發(fā),對(duì)流程引擎的作用有個(gè)初步的認(rèn)識(shí)。另外,搜索公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師后臺(tái)回復(fù)“9”,獲取一份驚喜禮包。
3.1 BPM 流程引擎的組成單元
組織、角色、用戶、成員的組織架構(gòu)托管;
流程資源文件的配置、校驗(yàn)、存儲(chǔ)和執(zhí)行,對(duì)不同的流程節(jié)點(diǎn),流程引擎自動(dòng)結(jié)合配置、數(shù)據(jù)處理其對(duì)應(yīng)的業(yè)務(wù)邏輯,流程數(shù)據(jù)自動(dòng)處理;
表單配置、數(shù)據(jù)綁定,表單數(shù)據(jù)的根據(jù)流程配置自動(dòng)處理;
通用的數(shù)據(jù)接口;
3.1.1 組織架構(gòu)的設(shè)計(jì)

3.1.2 流程設(shè)計(jì)器
流程設(shè)計(jì)器包含左側(cè)的分組節(jié)點(diǎn)列表,和右側(cè)的畫(huà)布。左側(cè)的節(jié)點(diǎn)可以如下進(jìn)行設(shè)計(jì)。

問(wèn)題:對(duì)于一個(gè) XML 或 JSON 格式的流程圖,如何進(jìn)行解析?
不同的節(jié)點(diǎn),按照不同的業(yè)務(wù)場(chǎng)景,配置不同的配置項(xiàng)。比如,對(duì)于 Human Node 需要配置審批人,配置審批環(huán)節(jié)的展示表單,審批環(huán)節(jié)能夠修改哪些字段,哪些字段的修改要進(jìn)行留痕等。
3.1.3 表單設(shè)計(jì)器


這種是按照表單相關(guān)數(shù)據(jù)表,生成出一個(gè)表單,然后對(duì)表單字段進(jìn)行配置和數(shù)據(jù)綁定。


這種是 Drag&Drop 控件,然后配置控件的屬性,如綁定字段等。另外,搜索公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師后臺(tái)回復(fù)“9”,獲取一份驚喜禮包。

這種是 Drag&Drop 控件,無(wú)需關(guān)聯(lián)數(shù)據(jù)庫(kù)表字段的表單

數(shù)據(jù)表生成表單的概要流程如下圖所示。

拖拽控件綁定數(shù)據(jù)表字段的概要流程如下。

拖拽控件無(wú)需綁定數(shù)據(jù)表字段的概要流程。使用 NoSQL 的 Document 記錄或使用 RDS 提供的 JSON 類(lèi)型進(jìn)行保存會(huì)比較方便。

3.1.4 接口設(shè)計(jì)
結(jié)合 Activity 的接口設(shè)計(jì),如下圖所示

一些系統(tǒng)在創(chuàng)建一個(gè)流程任務(wù)的時(shí)候,要先按照流程模板先創(chuàng)建一個(gè)應(yīng)用示例,再關(guān)聯(lián)發(fā)起人和備注,調(diào)用 RuntimeService,執(zhí)行到 StartNode,這類(lèi)設(shè)計(jì)因人而異,這么做略顯繁瑣。
3.2 基于流程引擎的項(xiàng)目開(kāi)發(fā)實(shí)踐
3.2.1 流程項(xiàng)目實(shí)踐流程
確定組織架構(gòu)
確定流程,包括流程布局、審批人設(shè)置、權(quán)限
確定表單信息(字段、類(lèi)型、數(shù)據(jù)源、校驗(yàn)規(guī)則)和表單樣式
確定頁(yè)面布局、樣式、數(shù)據(jù)字段、搜索、導(dǎo)入、導(dǎo)出
報(bào)表
3.2.2 組織架構(gòu)
組織架構(gòu)實(shí)現(xiàn),有兩種方法,一種是按照維度進(jìn)行數(shù)據(jù)管理,另一種是在同一棵組織架構(gòu)樹(shù)下進(jìn)行管理。
按照集團(tuán)、公司、部門(mén)、用戶等不同維度,進(jìn)行數(shù)據(jù)管理,比較常見(jiàn),這里不做討論。下圖為按維度維護(hù)數(shù)據(jù)的示例。

按照同一棵組織架構(gòu)樹(shù)進(jìn)行數(shù)據(jù)維護(hù),界面一般顯示為左樹(shù)右表。大多數(shù)商業(yè)化產(chǎn)品,都會(huì)將此組織架構(gòu)樹(shù)進(jìn)行內(nèi)存緩存,以方便審批人查找、開(kāi)窗選擇 OrgUnit、Role、User、Member 等場(chǎng)景。Member 的引入是為了解決一人多職等場(chǎng)景。一般發(fā)起流程的時(shí)候,需要帶出發(fā)起人擁有的 Member 列表,從而后續(xù)節(jié)點(diǎn)取合適的審批人。

對(duì)于組織架構(gòu)而言,需要考慮,系統(tǒng)本身要具備 OU 存儲(chǔ)的能力,對(duì)于沒(méi)有組織架構(gòu)的用戶,可以直接在系統(tǒng)的組織架構(gòu)中新建組織架構(gòu)。同時(shí),對(duì)于已有系統(tǒng)的客戶,可以通過(guò)組織架構(gòu)數(shù)據(jù)同步來(lái)進(jìn)行數(shù)據(jù)自動(dòng)維護(hù)。對(duì)于用 AD 域內(nèi)部管控的客戶來(lái)說(shuō),需要具備 AD 域身份認(rèn)證的能力。對(duì)于復(fù)雜場(chǎng)景,比如用戶是 SaaS 化等復(fù)雜場(chǎng)景,組織架構(gòu)也需要在系統(tǒng)內(nèi)部,支持使用 API 的方式來(lái)獲取組織信息。
所以在組織架構(gòu)設(shè)計(jì)的時(shí)候,要使用插件的方式來(lái)做,具體使用哪種插件,可以在配置文件中進(jìn)行配置。以下為一個(gè)商業(yè)產(chǎn)品的組織架構(gòu)操作界面示例。

常見(jiàn)的組織架構(gòu)操作還有組織架構(gòu)同步,比如流程系統(tǒng)同步微信企業(yè)號(hào)、釘釘?shù)?,這里不再展開(kāi)。
3.2.3 流程設(shè)計(jì)
我們想象的流程,可能是向下面的這種簡(jiǎn)單流程。

而實(shí)際項(xiàng)目,碰到的流程,一般是如下圖所示的情景。

初步看幾個(gè)流程的模型文件是什么樣的,先有個(gè)印象。

<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>
一個(gè)屏幕截圖都截不完的流程,如果用代碼去實(shí)現(xiàn)整個(gè)流程,其工作量和效率,可想而知。而實(shí)際做項(xiàng)目,使用基于流程引擎的產(chǎn)品來(lái)做項(xiàng)目的時(shí)候,只需要確定節(jié)點(diǎn)、節(jié)點(diǎn)配置、數(shù)據(jù)配置和權(quán)限即可。
問(wèn)題:一般流程,都帶有郵件通知的節(jié)點(diǎn),如何實(shí)現(xiàn)郵件通知節(jié)點(diǎn)?請(qǐng)考慮以下情景。
流程流轉(zhuǎn)和執(zhí)行的時(shí)候,會(huì)遇到各種情況的錯(cuò)誤,比如找不到審批人等,此時(shí)流程引擎要對(duì)數(shù)據(jù)做 rollback,而郵件通知節(jié)點(diǎn)的業(yè)務(wù)邏輯已經(jīng)執(zhí)行過(guò)了。
權(quán)限方面,對(duì)于流程資源,哪些部門(mén)可以申請(qǐng),哪些角色不可申請(qǐng),都應(yīng)該做流程控制。而在流程執(zhí)行過(guò)程中,流程數(shù)據(jù)、不是路程的相關(guān)人也都不應(yīng)該看到流程,處理過(guò)流程的審批人,不可以再對(duì)流程進(jìn)行處理等,都是權(quán)限方面要考慮的問(wèn)題。
3.2.4 表單設(shè)計(jì)
如下圖所示的表單,可以分析以下,一個(gè)流程表單有多個(gè)主表信息和多個(gè)子表信息。一般而言,如果是通過(guò)流程引擎做非流程的數(shù)據(jù)處理,子表通過(guò)主表 ID 來(lái)做關(guān)聯(lián),如果通過(guò)流程引擎做流程的數(shù)據(jù)處理,子表和主表通過(guò) TaskId 來(lái)做關(guān)聯(lián)。以下為示例。

流程系統(tǒng)需要表單設(shè)計(jì)器,一個(gè)流程的不同節(jié)點(diǎn)可以掛接不同的表單,以方便不同角色的人關(guān)注不同維度的流程信息
3.2.5 頁(yè)面設(shè)計(jì)
一般而言,對(duì)于流程的發(fā)起、審批、歷史記錄等,都是通用的系統(tǒng)界面。而一些業(yè)務(wù)場(chǎng)景,需要單獨(dú)做列表界面,以方便使用。對(duì)于已有門(mén)戶系統(tǒng)的客戶,需要融合其界面樣式。以下為曾經(jīng)做過(guò)的項(xiàng)目示例。


3.2.6 報(bào)表
由于不是所有客戶都有報(bào)表系統(tǒng),所以流程系統(tǒng)需要具備一個(gè)基本的報(bào)表功能。下圖為示例。

有報(bào)表系統(tǒng)的客戶,可以使用其商業(yè)版報(bào)表系統(tǒng),獲?。ㄖ苯尤 ?shù)倉(cāng))數(shù)據(jù)進(jìn)行展示。常見(jiàn)的報(bào)表系統(tǒng)有 FineReport、Tableau、PowerBI 等。
3.3 BPM 流程引擎架構(gòu)設(shè)計(jì)
3.3.1 流程引擎的架構(gòu)設(shè)計(jì)

3.3.2 發(fā)起流程

流程引擎處理過(guò)程

執(zhí)行節(jié)點(diǎn)處理過(guò)程

問(wèn)題:在流程引擎處理過(guò)程中,如果一個(gè)節(jié)點(diǎn)有多條連線,如何尋找 FromNodeId 是某個(gè) Node 的連線?
人工處理時(shí),指定連線 text
3.4 流程引擎架構(gòu)設(shè)計(jì)

3.4.1 業(yè)務(wù)識(shí)別
識(shí)別業(yè)務(wù)場(chǎng)景中的配置項(xiàng),使用集合或分組的方式,讓業(yè)務(wù)可配置
支撐業(yè)務(wù)流程過(guò)程的可配置化
支撐業(yè)務(wù)場(chǎng)景中的數(shù)據(jù),自動(dòng)處理
3.4.2 流程引擎的實(shí)現(xiàn)
資源相關(guān)服務(wù),資源加載,資源保存,資源加密等
配置項(xiàng)相關(guān)服務(wù)
PVM 虛擬機(jī)的實(shí)現(xiàn),即通過(guò)某個(gè)節(jié)點(diǎn)(發(fā)起時(shí)為開(kāi)始節(jié)點(diǎn))作為初始節(jié)點(diǎn),按照某個(gè)連線的 action 進(jìn)行節(jié)點(diǎn)的自動(dòng)執(zhí)行的虛擬機(jī)
數(shù)據(jù)配置、數(shù)據(jù)權(quán)限
流程數(shù)據(jù)和業(yè)務(wù)數(shù)據(jù)的自動(dòng)處理
4 商業(yè)機(jī)會(huì)
Business Process Analysis (BPA) 流程分析,幫助企業(yè)進(jìn)行流程調(diào)整和優(yōu)化
Process Assets Library(PAL)流程資產(chǎn)庫(kù),對(duì)企業(yè)流程進(jìn)行知識(shí)化沉淀,將制度和流程落地做綁定,讓審批人知曉流程中對(duì)應(yīng)的職責(zé)
Process Simulate 流程模擬,自動(dòng)化測(cè)試
Process Forecast 流程預(yù)測(cè)
低代碼平臺(tái)
更廣泛的機(jī)會(huì),在于業(yè)務(wù)領(lǐng)域 + 流程引擎,比如:DevOps、RPA、應(yīng)用與服務(wù)編排、數(shù)據(jù)編排、FaaS 編排等。
正文結(jié)束
1.Redis 只會(huì)用緩存?16種妙用讓同事直呼牛X
2.從零開(kāi)始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧
5.為什么國(guó)內(nèi) 996 干不過(guò)國(guó)外的 955呢?

