EOS工作流引擎工作原理.docx

上传人:大张伟 文档编号:10676708 上传时间:2021-05-30 格式:DOCX 页数:6 大小:18.93KB
返回 下载 相关 举报
EOS工作流引擎工作原理.docx_第1页
第1页 / 共6页
EOS工作流引擎工作原理.docx_第2页
第2页 / 共6页
EOS工作流引擎工作原理.docx_第3页
第3页 / 共6页
EOS工作流引擎工作原理.docx_第4页
第4页 / 共6页
EOS工作流引擎工作原理.docx_第5页
第5页 / 共6页
点击查看更多>>
资源描述

《EOS工作流引擎工作原理.docx》由会员分享,可在线阅读,更多相关《EOS工作流引擎工作原理.docx(6页珍藏版)》请在三一文库上搜索。

1、工作流引擎工作原理1 .工作流基础知识2 .工作流引擎工作原理本文是我在工作之余写的一点我对工作流的了解,我的理解不一定全是对的,可能会与引擎的真正的面目有出入。所以只能提供给大家一点参考。2.1. 工作流引擎核心调度算法工作流最重要的组成部分是它的核心调度算法,在我们没有深入研究它的工作原理之前我们认为它的工作原理是在工作项,活动和流程实例对象上加了一些标志位来驱动流程的运转。认为其引擎完全是个由数据库来驱动流程的引擎(安徽二期的工作流平台好象就是以库表来驱动流程的运转),其实它是由事件来驱动流程运转的引擎,数据库只是把引擎运转前后的状态持久化。在我近来在工作之余对其引擎的工作原理进行跟踪才

2、弄明白在帮助文档上 介绍的“事件驱动”的工作流引擎。2.1.1.工作流引擎的事件类型事件名称事件代码启动流程由线程来启动下个活动实例回退活动流程挂起启动挂起流程改变流程状态终止流程结束流程重起流程启动活动实例重起活动实例改变活动实例状态结束活动实例终止活动实例挂起活动实例启动挂起的活动实例挂起工作项启动挂起工作项改变工作项状态结束工作项终止工作项流程超时事件流程临近超时事件活动超时事件活动临近超时事件:以上的每个事件都是原子的不可分割的。其中一系列事件的集合通过引擎事件调度机制实现我们平时在工作中经常遇到的如启动流程,结束工作项等等。(在事件类型类中定义了种事件,但在事件工厂类中定义了种类型。

3、)2.1.2. 工作流事件调度机制事件的调度服务是在工作流引擎初始化时通过服务工厂类加载到内存中()。用户可以通过服务工厂类()取得的唯一事件服务实例进行事务调度。所有的事件程序入口都是事件类(),这个类其实是个接口,其有两个实现类,一个是单线程的实现类(在实现代码中 其实不是单线程,而是单例的对象),一个是多线程的实现类,(其实现方式不在这里详细说 明,多线程的类后面又跟了一大堆的线程池实现代码),在事件服务类中有一个属性类是,这个类包含了事件的注册,事件的发布,事件的注册是一个静态代码块实现的。注册了上节描述的种事件,其实就是把相应的事件代码注册到相应的处理类,事件处理类共用个(,),对应

4、事件代码的前个数字;共有事件的发布有两种,一种是正常发布,一种是无异常的发布 (即在具体执行事件时关闭了异常处理)。所谓的事件发布是给事件服务类传递一个事件对象(类),这个事件对象包含了事件类型,线程名,事件,流程定义,活动定义,活动实例, 和工作项等等。以上简要的描述了事件模型, 下面来拿我们平时用的最多的一个构件: 结束工作项来详 细跟踪它的事件处理。结束工作项可能是最具有代表性的一个流程动作,因为在做这个时间后遍历了整个流程实例的流程:1, 用户通过引擎的调用类的方法,该方法通过服务工厂取得持久层的数据访问服务,并根据取得对象。做相关的判断后通过事件工厂类的方法创建个事件代码 为的事件对

5、象()。然后通过服务工厂类取得事件服务类把该事件对象发布给事 件处理服务。从此刻就开始了事件调度服务的运转。2, 事件服务类(拿单线程事件服务类做例子)拿到这个事件类后把该事件通过发 布该事件。具体的发布过程很简单,即判断该事件类型是否已注册,如果已经 注册则取到改事件代码的注册类。该代码是,则应取。然后调用的()方法,3, 类()中写到:()();则找到该方法,该方法开始做了相关的判断后做相关 标志位的修改:置当前工作项的状态为,然后判断当前活动是否结束。(大概的算法是取得已经结束的工作项和该活动总的工作项,取得活动定义的多工作项 是否启动。如果是多工作项则判断完成个数策略:是按百分比还是按

6、操作员个 数等等,做一系列的判断后得到应该结束的工作项,如果小于等于已经结束的工作项则该活动结束,没有启动多工作项则相应的处理要简单点),如果该活动已完成,则调用事件服务的结束活动实例事件;如果没有结束则判断工作项启 动的策略是还是,如果是则找本活动实例下的工作项状态为的工作 并启动它。4, 结束活动实例是调用事件工厂的方法,新建一个事件代码为的事件。用的方法发布该事件。到类中找到,该方法修改活动实例状态为,填写活动结束时间。 如果该活动注册了时限则取消活动时限的注册。如果该活动实例定义了结束活 动的触发动作则触发该动作(通过调用)。最后由事件工厂产生一个事件代码为的事件。由事件服务发布事件。

7、5, 启动下个活动实例的事件动作是事件工厂调用方法,该方法通过流程定义找到下个环节的转移条件,并根据转移条件和分支模式(全部分支: ;多路分支:; 单一分支:)生成一个环节定义列表。 引擎首先把未启动的活动实例和挂起的活 动实例找到,如果没有则生成一个活动实例。然后生成一个转移对象(),最后 把待启动的活动实例对象放到一个列表中。根据该列表中的活动定义的启动策 略(直接启动,待激活,由规则逻辑指定)来启动活动实例;如果是直接启动 活动实例则由事件工厂新建一个事件代码为的事件,如果待激活策略则由事件 工厂产生事件代码为的事件。同样如果在流程定义中定义了创建活动实例触发 的事件则触发该事件,方法做

8、了很多业务处理的事情,所以比较复杂。6, 事件服务调用方法,修改当前活动状态位为,并向时限管理服务注册时限,然后通过活动执行类的帮助类分派工作项,分派工作项的过程是判断是否是多工 作项,如果不是则按参与人员分派,如果是则判断多工作项的启动策略,启动 工作项业务处理比较复杂,并没有相应的事件代码对应,在这里不详细介绍。以上的六个步骤完成了我们平时最常用的完成工作项的方法。综上所述应该能够对工作流的事件调度机制有个清楚的认识,比如结束工作项的事件调度有 这几种事件的触发。同样还有我们平时比较常用的启动流程实例方法首先是创建一个流程实例,然后开始事件调度: ,最后是分派工作项。里也有自己的调度机制,

9、但在业务上要比简单的多,准确的讲只有两个概念:(步骤)和 (动作)。一个简单的调度过程它可能从一个步骤流转到另外一个步骤(或者有时候还 是停留在一样的步骤)。它的调度其实就是一个类:,这个类里面有两个方法:和基本实现了所有的调度(其实也不能算是调度,只能算是状态的迁移)。最大的优点是在执行调度过程中执行的一系列的 (在里叫服务模型, 在里叫展现逻辑),它在执行客户端的服务时的机 制时还是比较复杂的,如果感兴趣在工作之余可以看一下。还有个最近比较流行的开源的引擎,我没看过这个,好象现在又整合到下去了,好象很复杂。2.2.时限管理服务2.2.1.时限的分类时限名称时限代码活动提醒时限活动执行时限流

10、程提醒时限流程执行时限时限类型有两种:一种是一次触发完成时限,还有一种是循环触发(譬如隔多长时间进 行一次提醒)并可设置触发的次数。2.2.2.时限计算器在工作流引擎启动时就启动一个唯一实例的时限计算器,该类可以使用引擎默认的。也可以自己去实现一个自定义的计算方法, 在配置文件中注册要重写的类名即可。 引擎的时限 计算器只有两个方法,一个是计算结束时间,还有一个是计算提醒时间。其实是个静态类。2.2.3. 时限服务的启动在引擎中的时限服务有两个,一个是引擎启动的时候启动的时限服务,该服务初始化了时限对象列表;一个是在引擎启动后启动的服务,该服务是对列表中的时限对象进行轮询, 触发超时的时限对象

11、对应的触发事件,并移除该对象时限。时限的线程处理用了大量的过程化程序的结构,在这里还是比较绕人的。2.2.4. 时限的注册和移除在流程引擎中的时限服务其实就是在维护一个时限对象的列表,该列表记载了处于运行状态的活动的时限对象。在启动一个环节或启动一个流程时判断该活动或该流程的时限,如果该活动或该流程定义了时限则向时限服务注册该时限;在类中的注册方法的实现是调用时限服务类的方法,往时限对象列表()追加一条记录。在结束活动事件时或结束流程时如果是超时的操作则时限对象列表中没有该活动的时限对象, 因为该对象已被时限触发器触发并移除。 如果没有超时则要把这个向量列表中的那条时限对象给去掉。 在类中的注

12、册移除方法的实现是调用时限服务类的方法, 往时限对象列表()移除一条记录。2.2.5. 时限事件的触发时限的触发完全是后台的线程做的事情。 该线程对时限服务所维护的时限对象列表进行该动作就是我们平时在中设的如果超该方法首先调用类然后修改时限类譬如在做指定下轮询, 如果发现有超时的对象则触发已定义好的动作,时则干什么事的触发动作。对时限的处理是通过这个类来实现的。是通过新建一个时限任务()让来执行。并向该类传递一个对象实例。 该对象有个方法就是到了预定时限时触发的方法。的方法, 即如果有触发事件的话就调用上节讨论的事件代码以开头的事件。的当前状态为,完成一次时限触发动作。3. 流程同步服务流程同

13、步服务是引擎自定义的一个对流程实例和流程定义的锁的定义,一个环节的参与人(中的方法)时先把当前的流程实例给琐住( () ) 。然后在方法结束后再把流程实例的锁给释放( () ) 。在同步服务中定义了两种类型的锁,一种是流程定义锁,一种是流程实例琐(两个) ,在加琐时检查改(流程实例或流程定义)是否已经在琐列表中,如果在则加琐。 在加琐与解锁之间是通过一个线程来操作锁列表()实现的。 其实现方法大概是在加锁的时候向添加一个锁对象, 然后把线程(); 在解锁的时候向减去一个锁对象, 并把线程 () 。流程同步服务的实现方式还是比较复杂的。尽管只用了七八个类。4. 组织机构管理提供了一套自己的组织机

14、构模型, 我们在安徽服务保障三期中引用了该模型。 该组织机构模型的服务会话面的实现是在配置文件中配置的,然后引擎采用的反射机制加载配置类(在引擎中有个叫做 “服务定位器” 来实现, 该服务定位器和我们平时用的一样, 只是它是从文件中读取服务定义,隐藏了具体寻址细节) 。如果不用提供的组织机构模型可以实现接口, 并实现里面的方法。 估计的原意是提供组织机构模型和引擎服务的松偶合, 但在其引擎的实现上好象并没有做到。类是引擎默认加载的组织机构模型会话面类。 该类定义了人员,角色, 机构等等, 类包 含岗位的组织机构模型 (目前的引擎的还不支持, 没有搞清楚没有把岗位纳入组织机构模型 中) ,但提供

15、的开源的组织机构模型中并不支持。5. 审计服务该服务记载了所有流程模板的变更和对流程实例的操作历史。引擎共定义了种审计类型,包括模板变更,启动流程,完成工作项等等。由于审计的类型代码和引擎的事件代码,所以引擎在中间做了一层映射, 把事件代码和审计代码一一对应 (审计代码多于事件代码)在审计过程中其实是往审计表中加一条历史记录。6. 日志服务引擎的服务很简单, 和我们平时用的差不多。 在打日志的时候传入唯一实例的日志上下文,在该类中定义了一条日志所需要的日志头,比如等级() ,操作员() , () ,时间戳()等等。然后在具体打某一条日志的时候把日志头和日志内容拼装起来形成一条日志。引擎的日志实

16、现了日志的读写, 引用了的和。 并提供了类似的方法前后拦截打日志的服务(不知道方法前后的拦截日志是在代码中人工加上的还是由代理自动加载的, 因为采用了时在编译的时候就把代码插入到要拦截的切入点中去) 。7. 持久层服务引擎的持久层和里的持久层是采用一样的设计。 大概是把数据库的字段和持久层的定义一一对应, 没有采用像或者的或者那样很复杂的。 由驱动持久层在系统中显的很高效, 但采用数据库和持久层的描述文件一一对应所以没有把关系数据的对象化做的很别致。 (没有深入的看过代码,可能我理解的不对) 。8. 引擎的缓存工作流引擎的缓存是通过一个来维护的。 用有以下几类缓存: 流程实例的缓存; 活动实例

17、的缓存;工作项的缓存;相关数据的缓存;相关数据的缓存;流程属性数据的缓存,以上几类的实例缓存个数是通过在配置文件中配置的, 还有一类流程模板的缓存是在引擎启动的时候就解析流程模板的文的定义(因为流程定义是通过文来存储在数据库中) ,解析成流程定义对象并加载到内存中。8.1. 缓存的配置工作流缓存的配置是在文件中配置的。共有以下几种配置:8.2. 缓存的实现在引擎启动的时候取得工作流配置信息, 如果允许使用缓存则初始化上面所述的六类缓存。在初始化的时候引擎默认缓存的存活时间为 1499700L 。缓存的大小为配置文件所配。这样则生成在里的六个类的实例。 每个都有一个的属性, 这里面存储了要缓存的

18、对象。 在类中又有一个对象属性,这个对象存储的是对象的集合。就是上面所述的六个类实例的集合。普元的开发人员把该对象起名为。 那么在取某个活动实例时就先中缓存中读取, 如果找到则直接返回,如果没有则从数据库中加载。引擎的缓存并不是直接把从数据库中取得的对象到中, 而是做了一层优化, 把从数据库中找到的对象封装成对象,该对象有个链表()的属性对象。该对象有前驱和后继节点,其节点就是我们要的对象。 其具体的优化策略和大多数缓存一样, 采用最近最多访问策略, 共 有两个列表维护,一个是最近访问对象位于首位,一个是最多访问对象位于首位。9. 引擎的精彩之处引擎设计上最精彩的地方应该是基于多线程的事件调度机制, 在事件处理是下层有个线程池处理事件,其中有个线程拿到了一个事件后就开始他的事件的发布和事件的迁移。 (多线程协同工作的程序设计我觉得应该是程序设计中最复杂的地方, 不但要屏弃所谓 “万物皆6 / 9

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 科普知识


经营许可证编号:宁ICP备18001539号-1