activiti流程卡住的解决方案

2018.05.22更新
之前一直认为只有Activiti集群重启会导致流程卡住,其实并不只有这种。数据库连接池被打满,serviceTask抛出了没有被捕获的异常,都会让流程卡住。
说解决方案之前还是先说下Activiti的核心概念和表。
processInstance: 代表一个流程,每个流程有自己的processInstanceId
execution: 我理解execution一个具体的执行对象,当流程执行到userTask/serviceTask的时候execution是task,当流程执行到Timer的时候表现为Timer,执行到子流程的时候表现为子流程的标识。对应的表就是act_ru_execution

Activiti流程在执行的时候是会定时存档的,当流程没写进去db、抛出异常的时候,流程会表现为卡在了上一个存档点。我们需要做的就是让流程从这个存档点恢复。
存档点表现为两种形式,task, job,分别对应userTask/serviceTaskTimer之类的非Task节点,也分别体现在act_ru_taskact_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 jobs = managementService.createJobQuery().processInstanceId(processInstanceId).list();
for (Job job : jobs) {
    managementService.executeJob(job.getId());
}

你可能感兴趣的:(activiti流程卡住的解决方案)