工作流管理系统
引擎调度需求
陈振双
目 录
1总调度引擎
1.1 概述:
在工作流系统中,工作流引擎系统包含一个或多个工作流引擎,这些引擎分布在多台计算机上,通过协作来共同执行工作流。协调工作需要有总调度引擎来完成,协调工作的基本功能就是根据外部要求,启动某指定流程,然后分配一个引擎来执行推进这个流程实例,对执行中出现的一些异常情况进行处理,保证流程能顺利执行完毕。
因此,总调度引擎需要具备的几个功能有:
1. 分配流程给引擎执行
2. 维护引擎列表,总调度和各个引擎之间需要进行心跳连接,当某引擎发生错误后,及时将该引擎中的过程实例重新分配给另外的引擎。
3. 实时将自己及各引擎的各种状态数据发送给工作流监控程序,使用户可以随时监控管理工作流各引擎的运行。
由此可见:总调度引擎可以说是整个工作流引擎系统推进,执行的总驱动器,所以保证总调度程序始终正常运行是至关重要的。
1.2外部激活流程要求的方式
流程的发起或称激活,其方式有以下三种,不管以哪种方式激活,总调度程序都需要通过消息队列来接收激活。
1.2.1 人工激活
多数流程的启动需要人为的信息输入或明确操作来激活,比如:订单处理流程,客户提交了订单信息(订单数据产生),点击确认或者提交,则激活订单处理流程的一个实例。
1.2.2 定时或限时激活
在特定时间,因为特定情况,符合特定条件,激活某个指定的流程和任务。
这种激活情况,比较而言会较少,主要是:某个流程中的某活动没有在需要的时间内达到某种预期状态,而激活另一个流程或任务。定时激活的方式可能会在以下情况出现:如订单处理流程,限制6天内出货,那么可以定义,到第5天的时候还没有接到发货通知,就启动一个流程,进行催办通知。
由以上可看出,这种激活方式受外来因素影响,并大多与一些流程任务一起出现。
1.2.3 外界消息激活
在多流程交互时,或者涉及嵌套流程,便会涉及这种方式,比如,流程A在结束或者过程中需要调用流程B,则会在适当位置,向流程B发送消息,以激活流程B的运行。
1.3 总调度接收启动请求
上面提到的几种激活方式,与的联系都通过消息系统,外部激活向消息队列发送激活消息来通知总调度引擎,总调度不断检索消息队列,处理发给自己的消息。在检查到“激活消息”后,从引擎列表中选取引擎进行分派。
激活消息会标明以下内容
1. 消息发出者
2. 消息发出时间
3. 消息接收者,应标明是发给总调度引擎的。
4. 消息种类:消息的类型就是“激活流程”的含义
5. 要激活的流程编号标识
1.4 分配流程给引擎
1.4.1 概述
总调度分配流程给引擎是通过在消息队列中写入“启动流程”消息实现的,引擎不断地检查消息队列,如有发给自己的“启动流程”消息,则根据自己维护的各引擎的状态,按一定的规则来进行分配调度计算。然后给计算出的引擎发送“启动流程”消息。该消息是需要回复的消息,也就是说在总调度发出了消息后,指定引擎接收到消息后,启动流程成功或失败都会发送一个相应消息,表示对“启动”消息执行的结果。
“启动流程”消息包含的内容如下:
1. 消息发出者,就是总调度程序
2. 引擎编号,说明是分配给哪个引擎的,也就是本消息的接收者
3. 消息类型:标明是分配的类型,“启动流程”
4. 流程编号:引擎要执行的流程的唯一标识号,引擎内的工作流机将根据此编号,下载(如已经下载则只须打开)流程定义文件,根据定义文件创建实例,并执行推进流程。
得到要分配的引擎。调度的分配算法规则可以有如下几种形式:
1.4.2 按引擎分类分配
按某种方法把引擎划分为几大类,每一类的引擎只处理所属类的流程,也就是说,引擎被专业化。比如按流程所属的业务范围分为:财务类,采购类,订货类等,如:一个属于财务的过程需要启动,总调度不需要查找全部的引擎,而只是在属于财务类的引擎中去进行分配。
如果没有对引擎分类,那么总调度在分配流程时,处理范围是全部运行的引擎,分类后,对一个流程可供分配的引擎范围被缩小了。
引擎的分类方法,可以根据具体企业的情况由用户进行设置,这就要求调度程序可以由用户根据需要在几种算法中自行设定。同时,还需要提供对引擎分类的操作接口
1.4.3 按空闲程度分配
在可供分配的引擎范围内按空闲程度统一分配,总调度引擎遍历全部可分配的引擎,计算出最空闲的引擎,将新过程分配给它。
“空闲”的含义不是指引擎内处理的流程实例最少,而是指引擎内的工作流机的利用程度低,空闲状态多。比如:一个引擎处理10个流程实例,但其中人工活动比较多,而人工响应比较慢,所以,其内部工作流机可能很多时候都处于空闲等待状态;另一个引擎处理的流程实例只有3个,但多是自动执行的活动,这样内部工作流机就可能基本上都处在忙碌状态。此时“空闲”的是第一个引擎,虽然它处理的流程实例多。
1.4.4 按任务量均衡分配
任务量均衡就指平衡各引擎上执行的流程实例数,分配时,在可分配的引擎范围内,查找运行流程实例数最少的引擎,分派其执行要激活的流程。
1.4.5 分配优先级顺序
如果两个或以上的流程同时请求启动,但此时只有一个引擎可供分配,那么调度程序就需要根据流程的优先级别来确定先分配哪个流程,高优先级的流程将被分配,而优先级低的则需要等待。
1.4.6 最少实例创建原则
根据工作流机对流程的启动情况,为达到最高的工作效率,可以将某流程与一个或一组引擎建立映射关系,当又有该流程的启动命令时,可以将命令直接转给有映射关系的引擎,由于该流程在这些引擎中已经实例化,再次分派后,可以省去创建流程实例的过程,而直接运行。
1.5 维护引擎列表
引擎在启动后,需要同总调度程序间保持“心跳”连接,这样总调度就可以跟踪每个引擎的状态,如:引擎是否在正常运行,引擎中运行着几个过程实例,实例执行的状态,内部空闲情况,引擎列表就是由这些状态值组成,同时引擎列表也是总调度引擎进行分配计算的依据。
维护引擎列表主要有两个目的:
1.5.1 保证过程实例正常运行
当一个引擎由于某种原因荡机或无法正常工作时,在其上运行的过程实例必须保证能够继续执行,不能引起业务工作流程的中断,这个工作就需要总调度程序完成。
1.5.1 .1 指定替代引擎
引擎如果在一定时间范围内无法维持同总调度的“心跳”连接,总调度程序就会认为该引擎已经不在工作状态,此时,需要将原来运行在该引擎上的过程实例收回,并将它们重新分配给其它正常运行的引擎。总调度从目前正常运行的引擎中找出任务量最小(运行流程实例最少)的一个,向其发送接管任务命令,命令指示其将停掉的那个引擎的工作全部接手,包括:继续运行原来的流程实例,处理消息队列中发给被接管的引擎的消息。
注意:继续执行实例的含义从原引擎中断时的状态开始继续执行。很重要的一步是恢复控制数据和相关数据。在新的引擎加载流程实例还未开始分配其活动执行时,新引擎需要一步加载流程实例上次中断时的所有控制数据,相关数据,和执行中的关键中间状态等。
1.5.1 .2 还原引擎任务
中断掉的引擎A重新启动后,又进入工作状态,此时总调度引擎要将被转移走的该引擎任务恢复回来。具体过程如下:
1. 通知替代引擎B,不再代替处理引擎A的流程和消息,同时,引擎B释放自己内部维护的原引擎A的流程实例。
2. 通知引擎A,开始正常工作,引擎A把原来自己处理的所以流程实例加载,并开始继续执行。
1.5.2 实时向监控报告状态数据
工作流管理监控系统要随时跟踪总调度引擎及各引擎的工作状况,以便进行管理,尤其对总调度引擎,需要及时发现运行异常,并保证总调度引擎的正常工作。所以,总调度引擎必须实时向监控传递自己和各引擎的状态,一方面可使监控程序根据这些数据刷新监控界面,同时,在发现异常后,能及时处理。
2调度引擎
引擎由一个或多个工作流机组成,工作流机负责完成过程中的各个活动,计算流程路径,推进流程,在计算了要进行的下一个任务后,调度引擎需要将其分配给引擎内的某一个工作流机来具体执行。此处的引擎任务调度指的就是将计算好的活动在内部各工作流机之间进行分配,而不是对流程任务的路由计算。
调度引擎的基本功能是:
1. 分配活动:遍历引擎内部的所有工作流机,将当前要执行的活动,分配给合适的工作流机。“活动”的含义不仅仅是流程中的,也包括外部传来的对流程实例操作的命令消息。
2. 管理工作流机:负责启动,停止工作流机,检查维护内部各个工作流机的运行状态,对因异常情况被阻塞或荡掉的工作流机,将原在其上运行的活动进行重新分配。同时需要重新启动工作流机。
2.1分配活动给工作流机
检查消息队列,查看是否有新的需要执行活动(被挂起的流程实例不需要分配)。遍历引擎内部的所有工作流机,找到目前处于空闲状态的工作流机,将要执行的活动分配给它执行。
对活动的分配方式不同于对流程的分配,不需要通过消息队列,而是直接对调用工作流机,将要执行的活动做为参数传递,安排工作流机来执行活动。
对工作流机的选择比较简单,只要工作流机空闲就可被分配活动,忙碌就需要等待。当对活动的选择就比较复杂,因为引擎中运行的流程实例个数会比工作流机多,也就是说,同一时刻,需要分配的活动会比可供分派的工作流机多。此时需要判断过程的优先级,通常优先级别高的要先分派。
这里有个特例,如果一个流程等待时间过长,调度引擎需要适当提供其优先级,避免其始终无法被执行。
对于工作流实例中的活动,工作流机在完成了该活动后,计算路径,定位下一个要执行的活动,并将新的要执行的活动写入消息队列,提示引擎进行下一个活动的分配(并不一定会还分配给这个工作流机)。引擎在检查到此消息后,直接进行任务分配。如此循环,直到流程实例最终执行完毕。
命令型活动通常是针对实例的,由外部用户发送,这些消息被调度引擎转给工作流机,因为引擎内的所有实例数据是独立与工作流机的共享空间,因此,任何工作流机都可执行这些命令。执行后,实例的状态或某些数据发生变化。
2.2管理工作流机
对工作流机的管理主要有启动,停止,调用(分派活动)。
引擎系统初始化时,启动(创建)工作流机,并实时监控各工作流机的工作状态:忙碌中,空闲,阻塞,关闭。工作流机被创建后,首先处于“空闲”状态,被分配了活动后,进入“忙碌”状态,活动执行完再次进入“空闲”状态,等待分配新活动。
工作流机因为系统或其它原因,无法再正常工作,就会进入“阻塞”状态,如果被停掉则是“关闭”状态。调度程序在发现有工作流机的状态是阻塞或关闭时,首先需要将原本在其上执行的活动分配给其它工作流机,以保证流程的正常运行,然后需要重新启动该工作流机。使之重新工作。
3 与消息系统的交互
通过上面的描述,可以看出,引擎的各个调度程序要与外部交互,都要通过消息系统。各种消息按是否需要反馈分为两大类,
1. 需要反馈的消息:在消息发到队列后,调度程序需要得到消息的反馈情况,确定消息是否被接收者 接收或处理,已经处理的结果成功或失败。
2. 无反馈消息:在消息成功发到消息队列后,发送方(调度程序)无须再对其观察,也就是不管接收方有没有处理该消息,无反馈消息也同样有时间限制,这个限制时间是允许消息在队列中存在的时间。
a) 如果规定时间内接收方接收了该消息,那么队列会立即删除消息。
b) 接收方一直没有处理这个消息,在超过了限定时间后,队列删除消息。
3. 反馈消息:针对某条消息进行回应,标明其处理的结果成功或失败。蓑衣这种消息会标明回应的消息编号,同时将原消息体做为一个附件信息携带。
3.1 与调度程序有关的消息
3.1.1 激活流程消息
消息种类:需要反馈
发起者:外部调用或用户
接收者:总调度引擎
消息含义:外部用户指定要激活某个引擎, 总调度引擎接收到消息后,按调度原则计算应出分派的引擎,随后根据分派是否成功发送回馈消息。
3.1.2 启动流程
消息种类:需要反馈
发起者:总调度引擎
接收者:调度引擎
消息含义:总调度引擎在计算出要分派的引擎后,向消息队列发送本消息,通知某引擎为指定的流程创建实例,并运行实例。
3.1.3 任务替代
消息种类:需要反馈
发起者:总调度引擎
接收者:调度引擎
消息含义:指定某引擎接替指定的调度引擎的全部工作,接收消息的调度引擎加载要替代引擎的所有过程实例,同时接收处理原发给替代引擎的所有消息。同时,在处理替代引擎中的实例或消息需要反馈时,也以替代引擎的名义发送消息。
3.1.4 停止任务替代
消息种类:需要反馈
发起者:总调度引擎
接收者:调度引擎
消息含义:在被替代的引擎重新进入工作状态后,需要从替代者那里将转移出去的流程实例取回处理权,首先需要替代者停止对这些实例的控制,这就是本消息的目的。
3.1.4 挂起流程
消息种类:需要反馈
发起者: 外部用户
接收者: 调度引擎
消息含义:外部用户出于某种需要,要求暂时停止某个流程实例的运行,发送该消息给队列,调度引擎接到消息后,将其做为一个活动分派给一工作流机执行,执行后,流程实例状态变为“挂起”。调度引擎不再对挂起的流程实例分派工作流机。
3.1.5 重启流程
消息种类:需要反馈
发起者: 外部用户
接收者: 调度引擎
消息含义:本消息是和 “挂起流程”相对的,要将某个被挂起的流程实例重新开始运行,挂起和重启都是在同一个引擎上进行的实例操作。同样由调度引擎接收后转发给工作流机
3.1.6 结束流程
消息种类:需要反馈
发起者:工作流机
接收者:调度引擎
消息含义:工作流机在执行完某一流程实例的最后一个活动后,发送本消息,告知调度引擎本实例已完成,并将被销毁。
3.1.7 终止流程
消息种类:需要反馈
发起者:工作流机
接收者:调度引擎
消息含义:某实例执行中,由于定义错误或条件不符合等因素,导致流程非正常终止,工作流机需要发送“终止”消息给调度引擎,通知其流程实例已成为“终止”状态。
3.1.8 流程实例状态消息
消息种类:无需反馈
发起者:调度引擎
接收者:管理监控程序
消息含义:发送各流程实例当前所处的状态,使得管理监控程序能跟踪流程的状态。
3.1.9 引擎状态:
消息种类:无需反馈
发起者:总调度引擎
接收者:管理监控程序
消息含义:发送系统内各引擎当前的工作状态,使得管理监控程序能跟踪引擎的状态。
3.1.10 活动完成消息
消息种类:需要反馈
发起者:工作流机
接收者:调度引擎
消息含义:工作流机完成某活动后,发送此消息,指明下一个要执行的活动。调度引擎接收后,就会为下一个活动分派工作流机,同时也标志当前的工作流机空闲下来,可以再次被分派活动。
3.1.11 响应消息
消息种类:无须反馈
发起者:上述消息的各个接收者
接收者:上述消息的发起者
消息含义:接收者在处理完“需反馈”的消息后,向消息队列写入响应消息,表示自己已经处理了消息。原消息发起者根据响应确定下一步操作。