LiteFlow 是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑。通过支持热加载规则配置,开发者能够即时调整流程步骤,将复杂的业务如价格计算、下单流程等拆分为独立且可复用的组件,从而实现系统的高度灵活性与扩展性。
一、基础概念
1.1 组件(Component)
LiteFlow 的核心概念是组件,组件是业务逻辑的最小单元。每个组件都对应一个具体的业务操作,例如“发送邮件”“计算价格”等。组件之间通过规则进行编排,形成完整的业务流程。
liteflow
的组件在规则文件中即对应的节点,组件对应的种类有很多,具体的如下所示:
- 普通组件
普通组件需要集成的是 NodeComponent
, 可以用在 when 和 then 逻辑中,具体的业务需要在 process 中去执行。同时在 node 节点中,可以覆盖 iaAccess 方法,表示是否进入该节点执行业务逻辑,isContinueOnError 判断在出错的情况下是否继续执行下一个组件,默认为 false。 isEnd 方法表示是否终止流程,默认为true。
- 选择组件
选择组件是通过业务逻辑来判断接下来的动作要执行哪一个节点,类似于 Java中的 switch , 在代码中则需要继承 NodeSwitchComponent
实现 processWitch 方法来处理业务。
# flow 规则表达式 选择组件
SWITCH(a).to(b, c);
# processWitch 表达式需要返回的是 b 或者 c 字符串来执行相应的业务逻辑
# flow 规则表达式 条件组件
IF(x, a, b);
- 条件组件
条件组件称之为 if 组件,返回的结果是 true 或者 false, 代码需要集成 NodeIfComponent
重写 processIf 方法,返回对应的业务节点,这个和选择组件类似。
在官方文档中,还有次数循环组件,条件循环组件,循环迭代组件,和退出循环组件,其应用场景比较复杂,可以使用简单的普通组件来替代,毕竟是轻量级的规则引擎,主要作用就是为了编排流程顺序,复杂的场景就升级使用工作流了
1.2 规则(Rule)
规则定义了组件之间的执行顺序和条件。LiteFlow 支持多种规则文件格式,如 XML、JSON、YAML 等,也支持从本地文件系统、数据库、ZooKeeper、Nacos、Apollo 等多种方式加载规则。
在我上一段实习中,就是通过Apollo配置不同场景下的多种任务编排实现实时生效
# 文件编排, then 代表串行执行 when 表示并行执行
# 串行编排示例
THEN(a, b, c, d);
# 并行编排示例
WHEN(a, b, c);
# 串行和并行嵌套结合
THEN( a, WHEN(b, c, d), e);
# 选择编排示例
SWITCH(a).to(b, c, d);
# 条件编排示例
THEN(IF(x, a),b );
1.3 上下文(Context)
上下文用于在组件之间传递数据。LiteFlow 提供了灵活的上下文机制,可以在流程执行过程中存储和共享数据。这里实际上在代码里定义一个全局变量在整个流程中进行流传即可
1.4 参数配置
在 liteflow
中,需要配置的内容有规则文件地址,节点重试(执行报错时可以进行重试,类似于 spring-retry), 流程并行执行线程池参数配置,流程的请求ID配置。
liteflow:# 规则文件 失败重试次数 打印执行日志 监控日志ruleSource : liteflow/*.el.xmlretry-count: 0print-execution-log: truemonitor:enable-log: trueperiod: 300000request-id-generator-class: com.platform.orderserver.config.AppRequestIdGenerator# 上下文的最大数量槽slot-size : 10240# 线程数,默认为64main-executor-works: 64# 异步线程最长等待时间 秒when-max-wait-seconds: 15# when 节点全局异步线程池最大线程数when-max-workers: 16# when 节点全局异步线程池队列数when-queue-limit: 5120# 在启动的时候就解析规则parse-on-start: trueenable: true
二、基础用法
2.1 引入依赖
在 Spring Boot 项目中,可以通过以下方式引入 LiteFlow 依赖:
<dependency><groupId>com.yomahub</groupId><artifactId>liteflow-spring-boot-starter</artifactId><version>2.10.6</version>
</dependency>
2.2 定义组件
通过 @LiteflowComponent
注解定义组件,并实现具体的业务逻辑
@LiteflowComponent("sendEmail")
public class SendEmailComponent extends NodeComponent {@Overridepublic void process() throws Exception {System.out.println("发送邮件");}
}
2.3 编写规则文件
在 flow.xml
文件中定义规则,也可以在代码中自定义实现EL规则
xml定义方式
<flow><chain name="test_flow">THEN(prepareTrade, grantScore, sendMq, WHEN(sendEmail, sendPhone));</chain>
</flow>
代码中定义方式
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.el.ELBus;
import com.yomahub.liteflow.el.ThenELWrapper;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.spring.SpringFlowExecutor;
import org.springframework.beans.factory.annotation.Autowired;import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class LiteFlowDemo {@Autowiredprivate SpringFlowExecutor flowExecutor;public void buildAndExecuteFlow() {// 假设有一个配置列表,每个配置项对应一个处理器List<Map<String, Object>> configList = new ArrayList<>();configList.add(Map.of("name", "processor1"));configList.add(Map.of("name", "processor2"));// 假设有一个处理器名称映射表Map<String, String> processorNameMap = Map.of("processor1", "component1","processor2", "component2");// 构建 EL 表达式ThenELWrapper finalEL = ELBus.then();for (int i = 0; i < configList.size(); i++) {Map<String, Object> config = configList.get(i);String name = (String) config.get("name");if (!processorNameMap.containsKey(name)) {System.out.println("No component exists for name: " + name);continue;}String processor = processorNameMap.get(name);finalEL.then(ELBus.node(processor).data("param" + i, "data" + i));}// 执行流程LiteflowResponse response = flowExecutor.execute2Resp("mainFlow", new DefaultContext());if (response.isSuccess()) {System.out.println("Flow executed successfully");} else {System.out.println("Flow execution failed");}}
}
2.4 执行流程
通过 FlowExecutor
执行流程:
LiteflowResponse response = flowExecutor.execute2Resp("test_flow", new DataRequest());
三、适用场景
LiteFlow 适用于拥有复杂逻辑的业务场景,例如:
- 电商下单流程:包括订单创建、库存扣减、支付处理、通知发送等多个步骤。
- 价格计算引擎:根据不同的规则和条件计算商品价格。
- 数据处理流程:在数据处理中,需要按顺序执行多个步骤。
四、与 Java 设计模式的相似性
4.1 策略模式
LiteFlow 的组件类似于策略模式中的策略类,可以根据不同的规则动态选择执行的组件。
4.2 模板方法模式
LiteFlow 的流程定义类似于模板方法模式中的模板方法,定义了业务流程的骨架,而具体的组件实现则类似于模板方法中的具体步骤。
4.3 责任链模式
LiteFlow 的组件可以通过规则进行串联,类似于责任链模式中的责任链,每个组件负责处理一部分逻辑。
五、实战使用
5.1 电商订单处理案例
假设在一个电商系统中,订单完成后需要进行积分发放、消息发送,并行发送短信和邮件。可以通过以下方式实现:
xml
<flow><chain name="orderCompleteFlow">THEN(prepareTrade, grantScore, sendMq, WHEN(sendEmail, sendPhone));</chain>
</flow>
5.2 动态规则更新
LiteFlow 支持热加载规则文件,可以在不重启应用的情况下更新规则。例如,将规则文件存储在数据库或配置中心(如 Nacos),修改规则后可以实时生效。
5.3 监控与日志
LiteFlow 提供了详细的执行日志和监控功能,可以记录每个组件的执行时间、执行结果等信息,方便排查问题。
5.4 高级特性
- 组件降级:在某些组件执行失败时,可以选择降级处理。
- 组件继承:可以通过继承的方式复用组件逻辑。
- 组件回滚:在流程执行失败时,可以选择回滚到之前的步骤。
六、总结
LiteFlow 是一个功能强大且灵活的规则引擎框架,适用于复杂的业务流程编排。通过组件化的方式,可以将复杂的业务逻辑拆分为独立的组件,通过规则进行编排,实现系统的高度灵活性和扩展性。同时,LiteFlow 提供了丰富的功能,如热加载、监控、日志等,方便开发者使用。
扩展问题自测
1. LiteFlow 的核心概念是什么?它是如何实现规则编排的?
LiteFlow 是将复杂逻辑抽解为一个个可复用的组件化,通过组件间的自由搭配实现灵活编排。以及利用Apollo或Nacos这些注册中心进行实时热更新
组件间的自由搭配是通过规则链实现的
{"chainId": "recommendChain","name": "推荐链路","condition": "A > B > C "
}
总结:通过 组件化 + 规则链 实现编排,通过注册中心监听配置变更实现热更新
2. LiteFlow 规则节点(Component)的执行机制是怎样的?支持哪些执行模式?
- 执行机制
- 初始化组件,通过@
LiteflowComponent
组件进行组件注册 - 解析规则链:解析规则链中组件执行链路
- 执行规则链
- 执行模式
- 顺序模式:"condition": "A > B > C" ABC顺序执行
- 并行执行:"condition": "A && B && C" 我们的业务中,对商品的多路召回就是并行的
- 选择执行 "condition": "A | B | C" 只执行多个流程中最先完成的组件
- 条件执行 "condition": "A WHEN(B > C)"
A
先执行,然后判断是否执行B > C
这条链路。
适用于 根据外部参数动态决定执行路径。
- FOR 循环 "condition": "FOR(A, 3)" 适用于 重复性任务,如轮询、批量处理等
- WHILE 循环 "condition": "WHILE(A, isContinue())" 适用于 动态决策的业务场景,如轮询、流式处理
- 失败处理 "condition": "A THEN(B)
A
失败后,会执行B
作为补偿措施。适用于 容错、降级、回滚等场景
3. LiteFlow 的规则是如何定义和加载的?
三种方式进行规则定义与加载
- json格式,在配置文件进行配置
- xml格式,同上
- java代码中动态注册规则链(推荐系统目前使用方式)
4. LiteFlow 规则流转时,如何保证数据在多个节点之间的传递?
LiteFlow实际上也是参考了责任链模式,通过一个全局变量作为上下文进行数据流转。LiteFlow里这个上下文变量叫做Slot(上下文容器)
LiteFlow 的 Slot
是一个 线程隔离的上下文容器,用于存储和管理整个流程中的数据,类似于 ThreadLocal
,但更适用于 流程级别的数据共享。
每次执行规则链时,LiteFlow 都会为当前执行实例创建一个 独立的 Slot,不同的请求不会相互影响。
LiteFlow 通过 ThreadLocal + 对象池 机制来管理 Slot,确保:
- 每个请求拥有独立的 Slot 实例,数据不会互相污染。
- Slot 复用机制 提高性能,避免频繁创建对象。
总结
LiteFlow 通过 Slot(数据槽)在多个节点之间传递数据,相当于流程级别的全局上下文。
Slot 的作用类似责任链模式中的 Context,存储数据供整个规则链使用。
每个请求拥有独立的 Slot,避免线程安全问题,同时通过对象池优化性能。