2018.05.22更新
之前一直认为只有Activiti集群重启会导致流程卡住,其实并不只有这种。数据库连接池被打满,serviceTask抛出了没有被捕获的异常,都会让流程卡住。
说解决方案之前还是先说下Activiti的核心概念和表。
processInstance
: 代表一个流程,每个流程有自己的processInstanceId
execution
: 我理解execution一个具体的执行对象,当流程执行到userTask/serviceTask的时候execution是task,当流程执行到Timer的时候表现为Timer,执行到子流程的时候表现为子流程的标识。对应的表就是act_ru_execution
Activiti流程在执行的时候是会定时存档
的,当流程没写进去db、抛出异常的时候,流程会表现为卡在了上一个存档点
。我们需要做的就是让流程从这个存档点恢复。
存档点表现为两种形式,task
, job
,分别对应userTask/serviceTask
和Timer
之类的非Task节点,也分别体现在act_ru_task
和act_ru_job
表中。通过processInstanceId
可以查到。
针对于job
形式的存档点,下面已经说明了怎么继续,对于task
类型,需要通过下面的代码将流程继续
ProcessInstance processInstance = processInstaceService.getProcessInstanceById(processInstanceId);
Task currentTask = processTraceService.getCurrentTaskInfo(processInstance);
if (currentTask != null) {
taskService.complete(currentTask.getId());
}
需要注意的是,如果流程中有使用call_activity,这种调用子流程是会生成独立的processInstanceId的。如果任务卡在call_activity中,则继续整个流程的processInstanceId需要是子流程的processInstanceId。
一、重新发布、重启、机器故障都会导致JVM挂掉,这时正在进行中的activiti
流程会怎么处理?
用户手册上已经告诉我们,activiti流程会在遇到wait status
节点之后将执行结果持久化到数据库中,即做一次transaction的submit。如果JVM突然挂掉,这个时候,正在执行的节点是来不及提交事务的。流程会停在上一个节点的wait status
处,在act_ru_job
表中可以通过process_instance_id_
找到它。一般处于message
或者timer
type.
二、JVM重新启动后,未完成的流程要怎么恢复?
还好activiti给我们提供了api,通过managementService.executeJob(jobId)
强制执行job。执行这个job之后,相当于流程又接上头了,可以继续往下执行。代码如下
List<Job> jobs = managementService.createJobQuery().processInstanceId(processInstanceId).list();
for (Job job : jobs) {
managementService.executeJob(job.getId());
}
网友评论