编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

初试Liteflow引擎,业务组件编排(lite flow)

wxchong 2024-07-03 02:27:27 开源技术 15 ℃ 0 评论

基于 liteflow-2.11.4.2版本,同时通过编码的方式进行配置 liteflow规则

官方说明

LiteFlow就是为解耦复杂逻辑而生,如果你要对复杂业务逻辑进行新写或者重构,用LiteFlow最合适不过。它是一个轻量,快速的组件式流程引擎框架,组件编排,帮助解耦业务代码,让每一个业务片段都是一个组件,并支持热加载规则配置,实现即时修改。

使用LiteFlow,你需要去把复杂的业务逻辑按代码片段拆分成一个个小组件,并定义一个规则流程配置。这样,所有的组件,就能按照你的规则配置去进行复杂的流转。

依赖

<dependency>
  <groupId>com.yomahub</groupId>
  <artifactId>liteflow-core</artifactId>
  <version>2.11.4.2</version>
</dependency>

配置

public static void main(String[] args) {
    // 1. 定义liteflow node的信息
    FlowBus.addManagedNode("a", new ACmp());
    FlowBus.addManagedNode("b", new BCmp());
    FlowBus.addManagedNode("c", new CCmp());
    FlowBus.addManagedNode("d", new DCmp());
    // 2. 定义liteflow chain信息
    LiteFlowChainELBuilder.createChain()
    .setChainId("chainA") // chain 名称
    .setEL("THEN(a,WHEN(b,c),d)") // chain的表达式,then表达式是串行的,when 是异步执行的
    .build(); // 创建chain

    // 3. 创建FlowExecutor 执行指定的chain
    FlowExecutorHolder.loadInstance(new LiteflowConfig())
    // 配置自定义的上下文对象ContextBean,在NodeComponent中可以通过getSlot().getContextBean获取
    // param参数是配置为请求的上下文,也是属于slot中的一部分数据
    // slot 数据槽作为每个执行链的共享数据,各执行链之间的数据是隔离的
    // 为什么设置一个slot对象出来呢?
    // 个人理解是为了统一管理,因为要考虑串行、并行的情况,如果将一个对象在各个线程中传递,会变得很复杂
    // 将slot统一管理,只需要传递当前链使用slotIndex 即可
    .execute2Resp("chainA", null, new ContextBean());
}

定义node信息

FlowBus.addManagedNode("a", new ACmp());
FlowBus.addManagedNode("b", new BCmp());
FlowBus.addManagedNode("c", new ACmp());
FlowBus.addManagedNode("d", new BCmp());

node是 liteflow中执行业务逻辑的节点信息,每个node是一个组件,负责处理其中的一个业务逻辑,是组件执行链(chain)的子元素。

定义chain

    // 2. 定义liteflow chain信息
    LiteFlowChainELBuilder.createChain()
    .setChainId("chainA") // chain 名称
    .setEL("THEN(a,WHEN(b,c),d)") // chain的表达式,then表达式是串行的,when 是异步执行的
    .build(); // 创建chain

liteflow 真正运行的就是具体的链,链将每个节点进行组合,作为其真正的业务控制逻辑来执行。

其中:

chianId 配置该条链的编号,后续可以通过该编号进行执行

EL 配置链的执行表达式

上述的执行流程图如下:

其中 THEN表达式是串行的,WHEN表达式是并行处理的

执行链

// 3. 创建FlowExecutor 执行指定的chain
    FlowExecutorHolder.loadInstance(new LiteflowConfig())
    // 配置自定义的上下文对象ContextBean,在NodeComponent中可以通过getSlot().getContextBean获取
    // param参数是配置为请求的上下文,也是属于slot中的一部分数据
    // slot 数据槽作为每个执行链的共享数据,各执行链之间的数据是隔离的
    // 为什么设置一个slot对象出来呢?
    // 个人理解是为了统一管理,因为要考虑串行、并行的情况,如果将一个对象在各个线程中传递,会变得很复杂
    // 将slot统一管理,只需要传递当前链使用slotIndex 即可
    .execute2Resp("chainA", null, new ContextBean());

在定义完节点和链的信息后,就可以开始执行具体的链来完成业务逻辑,通过 FlowExecutorHolder.loadInstance(new LiteflowConfig())来获取 FlowExecutor对象(该对象建议是单例,因为创建比较重)。

数据槽

因为liteflow中的chain是由不同的node组件组成的,那在不同的组件中如何传递数据呢?

liteflow 会在执行每个chain时,分配一个唯一的数据槽(slot)给当前的请求,每个流程的数据槽都是完全隔离的,每个组件都是不传递参数,最终都是以这个数据槽来数据交互的。

为什么设计一个slot对象出来呢?

个人理解是为了统一管理,因为要考虑串行、并行的情况,如果将一个对象在各个线程中传递,会变得很复杂

将slot统一管理,只需要传递当前链使用slotIndex 即可。

slot也提供了以下方法来处理不同场景的数据获取:

// 获取某个节点的输入数据
public <T> T getInput(String nodeId)
// 获取某个节点的输出数据
public <T> T getOutput(String nodeId)
// 设置某个节点的输入数据
public <T> void setInput(String nodeId, T t)
// 设置某个节点的输出数据
public <T> void setOutput(String nodeId, T t)
// 获取流程的初始参数数据,由execute2Response中的param参数传递
public <T> T getRequestData()
// 设置初始参数
public <T> void setRequestData(T t)
// 获取属于chain的数据
public <T> T getChainReqData(String chainId)
// 设置属于chain的数据
public synchronized <T> void setChainReqData(String chainId, T t)

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表