最近在使用Camunda工作流引擎实现微服务的编排工作,根据业务场景需要某些任务节点在出现异常的情况下,进行异步重复操作,且不能影响之前节点的执行结果,即事务不能回滚。配置好工作流程后,本以为可以顺利执行,结果出现Camunda JOB 没有执行的情况,流程停留在时钟节点上。该问题耗费了两天的时间才解决。
环境版本说明:
camunda-bpm-spring-boot-starter-webapp 3.0.5
spring boot 2.2.5.RELEASE
Oracle 数据库 ojdbc的版本:11.2.0.3.0
示例流程图如下:
“任务二”节点在出现异常情况情况下,抛出了BpmnError给流程引擎,这时Camunda流程引擎应该捕获该该错误,然后通过JOB Executor 进行异步调度执行,但是这个调度任务并不起作用,节点卡在了时钟节点上,且不再继续执行。
是什么原因导致的呢?怎么解决呢?
经两天的源码调试和分析,发现调度任务不起作用的主要原因是Camunda Job Executor 在执行任务前,需要对任务添加乐观锁,但是每次加锁都是失败的,如图:
numberofJobsFailedToLock = 1, 而acquiredJobs Size 为0.在调试的期初,acquiredJobs是大于0的,这说明加锁是失败的,之前获取的需要执行的JOB任务被移除了,那么为什么会加锁失败呢?需要找到执行乐观锁的SQL才行,执行的SQL如下:
这个时候我们发现,返回值为【-2】,Camunda流程引擎对于【-2】这个值,认为是加锁失败的,这是就主要的原因了。
因为Camunda工作流引擎默认采用的是批量操作的方式,而我们使用的Oracle数据库版本为11.2。根据Oracle官方的解释,该版本在执行批量操作的时候,即使执行成功,但是不能正确返回执行成功的记录数,这个时候返回值为【-2】
好了,找到了本质的原因,想要解决这个问题,就需要关闭Camunda工作流引擎批量操作的方式.
方式一,在yml文件中添加配置,关闭批量处理操作:
方式二:使用Camunda的ProcessEnginePlugin 插件修改流程引擎的配置
经过测试,问题解决了。
总结:由于Oracle数据版本的问题,Camunda流程引擎中的采用批量操作都会被影响,如果希望使用Camunda的批量操作提升性能,Oracle需要采用12.* 以上的版本。
参考文档:
https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#executeBatch()
https://docs.camunda.org/manual/latest/user-guide/spring-boot-integration/configuration/