.net erp(辦公oa)開發平臺架構之流程服務概要介紹

背景
node

搭建一個適合公司erp業務的開發平臺。web

架構概要圖
 
數據庫


流程引擎開發平臺
  包含流程引擎設計器,流程管理平臺,流程引擎服務。目前只使用單個數據庫進行管理。
  流程引擎設計器
c#

   採用silverlight進行開發,本質是對流程模型進行設計,並生成xml。包含:人工節點,自動節點,並行開始節點,並行結束節點,消息節點,文本節點。
  示例模型定義圖形:
    
  示例模型定義xml:
api

<?xml version="1.0" encoding="gb2312"?>
<ProcessModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <BaseInfo>
    <Key>ddd</Key>
    <Title>新建模型</Title>
    <Description>發起人</Description>
    <CreateTime>0001-01-01T00:00:00</CreateTime>
    <Author>
      <StaffNo>34</StaffNo>
      <UserName>車江毅1</UserName>
    </Author>
    <Type>Common</Type>
    <Compilation>Debug</Compilation>
  </BaseInfo>
  <Variables>
    <Variable Name="myValue1" Value="今每天氣好晴朗" Mode="Flow" />
    <Variable Name="myValue2" Value="v2" Mode="Flow" />
    <Variable Name="myValue3" Value="v3" Mode="Flow" />
    <Variable Name="myValue4" Value="true" Mode="Flow" />
  </Variables>
  <Nodes>
    <BaseNode xsi:type="StartNode" Key="start1" Text="開始" Location="236 10">
      <Routes>
        <Route To="auto1" Text="" Location="0 0">
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
    </BaseNode>
    <BaseNode xsi:type="AutoNode" Key="auto1" Text="系統判斷" Location="236 95">
      <Routes>
        <Route To="man1" Text="線1" Location="0 0">
          <Code><![CDATA[myValue4=='true']]></Code>
          <RouteScripts />
        </Route>
        <Route To="人工2" Text="線" Location="0 0">
          <Code><![CDATA[myValue4=='false']]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
      <Scripts>
        <Script>
          <Code><![CDATA[api.Forword('http://webservice.webxml.com.cn/webservices/ChinaTVprogramWebService.asmx','getTVstationDataSet','theAreaID:2')]]></Code>
        </Script>
        <Script>
          <Code><![CDATA[api.UpdateVariable('063550')]]></Code>
        </Script>
      </Scripts>
    </BaseNode>
    <BaseNode xsi:type="ManNode" Key="man1" Text="人工1" Location="167 205">
      <Routes>
        <Route To="並行開始1" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
      <Participants>
        <Participant Mode="Code">
          <Code><![CDATA[api.Split('034','#')]]></Code>
        </Participant>
        <Participant Mode="Variable">
          <Code><![CDATA[myValue3]]></Code>
        </Participant>
      </Participants>
      <Solt OrderCount="2" Mode="Once" />
      <Decisions>
        <Decision Text="贊成" />
        <Decision Text="不一樣意" />
      </Decisions>
    </BaseNode>
    <BaseNode xsi:type="EndNode" Key="結束" Text="結束" Location="238 732">
      <Routes />
      <BeginScripts />
      <EndScripts />
    </BaseNode>
    <BaseNode xsi:type="ManNode" Key="人工2" Text="人工2" Location="324 203">
      <Routes>
        <Route To="並行開始1" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
      <Participants />
      <Decisions />
    </BaseNode>
    <BaseNode xsi:type="ParallelBeginNode" Key="並行開始1" Text="並行簽入" Location="237.047607421875 312">
      <Routes>
        <Route To="人工3" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
        <Route To="人工4" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
    </BaseNode>
    <BaseNode xsi:type="ParallelFinishNode" Key="並行結束1" Text="並行結束1" Location="240 571">
      <Routes>
        <Route To="消息1" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
    </BaseNode>
    <BaseNode xsi:type="ManNode" Key="人工3" Text="人工3" Location="95 378">
      <Routes>
        <Route To="自動1" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
      <Participants />
      <Decisions />
    </BaseNode>
    <BaseNode xsi:type="ManNode" Key="人工4" Text="人工4" Location="392 379">
      <Routes>
        <Route To="自動2" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
      <Participants />
      <Decisions />
    </BaseNode>
    <BaseNode xsi:type="AutoNode" Key="自動1" Text="自動1" Location="98 483">
      <Routes>
        <Route To="並行結束1" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
      <Scripts />
    </BaseNode>
    <BaseNode xsi:type="AutoNode" Key="自動2" Text="自動2" Location="394.714294433594 474.952362060547">
      <Routes>
        <Route To="並行結束1" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
      <Scripts />
    </BaseNode>
    <BaseNode xsi:type="MessageNode" Key="消息1" Text="消息1" Location="239 656">
      <Routes>
        <Route To="結束" Text="線" Location="0 0">
          <Code><![CDATA[]]></Code>
          <RouteScripts />
        </Route>
      </Routes>
      <BeginScripts />
      <EndScripts />
      <Participants />
      <MessageVariables />
      <TemplateKey>0</TemplateKey>
      <TemplateName />
    </BaseNode>
  </Nodes>
</ProcessModel>


  常規界面以下:
  
 
架構

流程管理平臺
  包含:流程模型管理,流程管理,流程任務管理,流程操做記錄,流程服務接口日誌查詢,流程異常查詢,流程流轉調試日誌查詢,開發者用戶管理等。
  能夠管理流程模型歷史版本及版本切換,流程異常時候的流程節點切換,流程任務的轉交等。
 界面以下:異步

 

流程服務
  包含:流程接口和流程任務接口。分佈式

    /// <summary>
    /// 業務流程服務接口
    /// </summary>
    public interface IProcessService
    {
        /// <summary>
        /// 獲取業務流程
        /// </summary>
        /// <param name="guid">業務流程ID</param>
        ProcessInfo GetProcessById(Guid guid);
        /// <summary>
        /// 批量獲取業務流程
        /// </summary>
        /// <param name="guids">多個業務流程ID</param>
        ProcessListInfo GetProcessesByIds(List<Guid> guids);
        /// <summary>
        /// 根據流程發佈者,獲取業務流程列表
        /// </summary>
        /// <param name="user">用戶的信息 參看UserInfo對象註釋</param>
        /// <param name="modelkeys">模型key  可選(多個)</param>
        /// <param name="keyword">關鍵詞(標題) 可選</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        ProcessListInfo GetProcessListByOriginator(UserInfo user, List<string> modelkeys, string keyword, int pageIndex, int pageSize);
        /// <summary>
        /// 根據流程參與者,獲取業務流程列表
        /// </summary>
        /// <param name="user">用戶的信息 參看UserInfo對象註釋</param>
        /// <param name="modelkeys">模型key 可選(多個)</param>
        /// <param name="keyword">關鍵詞(標題) 可選</param>
        /// <param name="nodekey">任務所在節點key 可選</param>
        /// <param name="state">任務完成狀態</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        ProcessListInfo GetProcessListByParticipant(UserInfo user, List<string> modelkeys, string keyword, string nodekey, EnumTaskStateQuery state, int pageIndex, int pageSize);
        /// <summary>
        /// 根據模型keys, 獲取業務流程列表
        /// </summary>
        /// <param name="modelkeys">模型關鍵詞 (多個)</param>
        /// <param name="keyword">關鍵詞(標題) 可選</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        ProcessListInfo GetProcessListByModel(List<string> modelkeys, string keyword, int pageIndex, int pageSize);
        /// <summary>
        /// 建立業務流程
        /// </summary>
        /// <param name="modelkey">業務流程對應的模型key</param>
        /// <param name="title">業務流程標題</param>
        /// <param name="description">業務流程描述</param>
        /// <param name="variables">業務流程使用變量 可選</param>
        /// <param name="user">業務流程發起人 參看UserInfo對象註釋</param>
        /// <param name="operationArgs">操做記錄 可選</param>
        /// <returns></returns>
        ProcessInfo CreateProcess(string modelkey, string title, string description, List<Variable> variables, UserInfo user, OperationRecordInfoArgs operationArgs);
        /// <summary>
        /// 更新業務流程
        /// </summary>
        /// <param name="guid">業務流程的ID</param>
        /// <param name="title">業務流程的標題</param>
        /// <param name="description">業務流程的描述</param>
        /// <param name="variables">業務員流程的變量 可選</param>
        void UpdateProcess(Guid guid, string title, string description, List<Variable> variables);
        /// <summary>
        /// 結束業務流程
        /// </summary>
        /// <param name="guid">業務流程的ID</param>
        void FinishProcess(Guid guid, UserInfo user, OperationRecordInfoArgs operationArgs);
        /// <summary>
        /// 建立流程操做記錄
        /// </summary>
        /// <param name="user">操做用戶不能爲空</param>
        /// <param name="operationArgs">操做記錄不能爲空</param>
        void CreateProcessOperationRecord(Guid guid, UserInfo user, OperationRecordInfoArgs operationArgs);
    }
/// <summary>
    /// 任務服務接口
    /// </summary>
    public interface ITaskService
    {
        /// <summary>
        /// 根據任務id,獲取任務
        /// </summary>
        /// <param name="id">任務id</param>
        /// <returns></returns>
        TaskInfo GetTaskByID(string id);
        /// <summary>
        /// 根據任務id,批量獲取任務
        /// </summary>
        /// <param name="ids">多個任務id</param>
        /// <returns></returns>
        TaskListInfo GetTasksByIDs(List<string> ids);
        /// <summary>
        /// 根據業務流程id,獲取任務信息列表
        /// </summary>
        /// <param name="state">任務狀態</param>
        /// <param name="processId">業務流程id</param>
        /// <returns></returns>
        TaskListInfo GetTaskListByProcessID(EnumTaskStateQuery state, Guid processId);
        /// <summary>
        /// 根據用戶,獲取任務信息列表
        /// </summary>
        /// <param name="user">用戶的信息 參看UserInfo對象註釋</param>
        /// <param name="state">任務狀態</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        TaskListInfo GetTaskListByUser(UserInfo user, EnumTaskStateQuery state, int pageIndex, int pageSize);
        /// <summary>
        /// 根據用戶和流程,獲取任務信息列表
        /// </summary>
        /// <param name="user">用戶的信息 參看UserInfo對象註釋</param>
        /// <param name="processId">業務流程id</param>
        /// <param name="nodekey">當前活動節點key 可選</param>
        /// <param name="state">任務狀態</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        TaskListInfo GetTaskListByUserAndProcess(UserInfo user, Guid processId, string nodekey,EnumTaskStateQuery state, int pageIndex, int pageSize);
        /// <summary>
        /// 根據業務流程模型key,獲取任務信息列表
        /// </summary>
        /// <param name="user">用戶的信息 參看UserInfo對象註釋</param>
        /// <param name="modelkeys">業務模型key 可選(多個)</param>
        /// <param name="nodekey">當前活動節點key 可選</param>
        /// <param name="state">任務狀態</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        TaskListInfo GetTaskListByUserAndModel(UserInfo user, List<string> modelkeys, string nodekey, EnumTaskStateQuery state, int pageIndex, int pageSize);
        /// <summary>
        /// 執行任務
        /// </summary>
        /// <param name="id">任務id</param>
        /// <param name="action">任務的動做 例如:「贊成」「不一樣意」</param>
        /// <param name="variables">流程參數 可選</param>
        /// <param name="operationArgs">操做信息 必填</param>
        TaskInfo ExecuteTask(string id, string action, List<Variable> variables, OperationRecordInfoArgs operationArgs);

        /// <summary>
        /// 轉交任務
        /// </summary>
        /// <param name="id">任務id</param>
        /// <param name="toUser">任務轉交人信息 參看UserInfo對象註釋</param>
        /// <param name="operationArgs">操做信息 傳null則無轉交操做記錄</param>
        TaskInfo TransferTaskWithOperationRecordInfoArgs(string id, UserInfo toUser, OperationRecordInfoArgs operationArgs);


分佈式架構概想
  分佈式拆庫方案:流程維度和用戶維度,流程維度數據庫按照流程定義模型的惟一標識hash,來拆分到不一樣的數據庫。全部流程建立和流程任務的建立都在不一樣的數據庫中。用戶維度數據庫按照用戶標識hash,來拆分到不一樣的數據庫。
  拆庫優勢:數據被拆分,不影響同一個業務流程流轉,性能會獲得提高。
  拆庫缺點:採用異步消息通知,作用戶代辦任務和完成任務冗餘及同步。採用BI工具或者hadoop等進行數據報表等分析。開發,維護複雜度等都會提高。
  結論:若是不是作大型產品或服務,不會進行分佈式架構。工具

(此文只作階段性的總結,也許對一樣作流程引擎的人有些啓發,也歡迎交流。分佈式相關架構能夠參考本人其餘文章)
oop

相關文章
相關標籤/搜索