背景
我们的项目背景是想利用现有的开源工作流引擎,二次开发一个给业务人员使用的流程编辑器,去执行一系列的自动化任务。对应bpmn里面就主要是service task节点,那么结合我们系统的现状------------微服务架构,很多业务代码是分散在不同服务中。
为什么会选到camunda
挺多的,常见的比如activity,flowable,camunda,一般像activity和flowable如果要去实现一个service task,你需要在引擎的服务包里面去写个实现类,然后再service task节点去把包名类名配置上。这样就有一个问题,不方便扩展,比如我其他业务服务增加了功能,也想并入工作流使用,那我除了在我业务服务里面写代码,引擎服务里面也要对应做实现。而camunda有一个实现方式“External Task”外部任务,,支持在引擎外去实现service task的逻辑,这个就很方便解耦了,我只需要把引擎部署之后便不需要再去动我的引擎服务代码,一切业务逻辑都在对应的业务服务实现。
外部任务
它的实现思路也很简单,是用mysql做了一个简单的订阅发布功能,节点上配置一个topic,每个启动的流程实例运行到这个节点,这个节点就会生产一条此topic的数据到库里面,然后你其他地方需要实现一个消费者去监听这个topic是否有记录,如果有则执行消费者这边写的逻辑代码。
这边是个简单例子,这里没有用camunda的springboot starter,是直接引了camunda依赖。
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-engine</artifactId>
<version>7.15.0</version> <!-- 请使用最新的版本 -->
</dependency>
这里的url跟默认是不同的,要跟引擎服务定义的保持一致。可以看出它这里实际调接口是去轮询查询并锁定外部任务记录。
ExternalTaskClient client = ExternalTaskClient.create()
.baseUrl("http://127.0.0.1:8705/api/origin") // Camunda服务器的地址
.asyncResponseTimeout(10000) // 长轮询超时时间
.workerId("test:1")
.build();
下面是具体某个外部任务的业务实现,这里subscribe方法里面填的就是在节点设置的topic
client.subscribe("receive-msg")
.lockDuration(1000) // 锁定任务的持续时间,单位为毫秒
.handler((externalTask, externalTaskService) -> {
// 在这里处理任务...
String eventName = (String) externalTask.getVariable("eventName");
Object userId = externalTask.getVariable("userId");
System.out.println("userId"+userId);
VariableMap variables = Variables.createVariables();
variables.putValue("city", "南京");
variables.putValue("temperature", 25);
externalTaskService.complete(externalTask,variables);
})
.open();