问答
- Q:LiteFlow支持事务么?
- Q:LiteFlow适用于什么场景?
- Q:是否可以做审批流或者角色轮转的流程?
- Q:是否可以运行到一半手动停止,然后下次继续运行链路?
- Q:为什么规则存储Nacos不支持拆分规则和脚本,而是需要保存整个XML?
- Q:对于通用组件进行复用编排,上下文类型该如何设置?
- Q:上下文里的数据是线程安全的吗?
- Q:LiteFlow性能如何?
- Q:是否支持逆向执行,来实现回滚等操作?
- Q:是否支持界面编排?
- Q:如何做跨服务的分布式编排?
- Q:flowExecutor.execute2Resp调用了,为什么取不到上下文中的参数
- Q:流程中是否如果有回调该如何处理
- Q:如果出现栈溢出怎么办
- Q:启动时出现NoSuchMethodError的错误是什么原因
# Q:LiteFlow支持事务么?
A:不能说支持或者说不支持,因为LiteFlow和事务没有本质上的关系。LiteFlow只不过在本地帮你把代码进行组件化和可编排化,事务还是按照原先的方式去做。例如,你完全可以加@Transactional
来开启spring事务:
@Transactional
public void testIsAccess() {
LiteflowResponse response = flowExecutor.execute2Resp("chain1", 101);
if (!response.isSuccess()){
throw response.getCause();
}
}
那么,这个链路中的所有组件,只要有一个组件发生异常,那么执行过的本地事务就会回滚,同理,你可以在任意地点加编程式事务。
同理,如果涉及到分布式事务,你也可以采用任意一种分布式事务的解决方案来做,这本质上已经脱离了LiteFlow的讨论范畴。
# Q:LiteFlow适用于什么场景?
A:LiteFlow适用于具有复杂逻辑,逻辑复用性比较强的业务系统,可以利用LiteFlow框架对业务进行解耦,编排,复用,动态更新,使代码更加优雅。
LiteFlow使用场景不限业务,只要你的业务系统可以根据业务边界来划分出来一个个独立的组件逻辑。既可以使用LiteFlow框架来优化你的代码。
# Q:是否可以做审批流或者角色轮转的流程?
A:其实在开篇LiteFLow简介已经有提到过,LiteFlow不做基于角色流转的流程,只做逻辑流程。并且LiteFlow在以后,也不会做基于角色流转的流程,因为LiteFlow要保持轻量和易用性,是一个无状态的流程编排工具。如果你的业务是基于角色流转的,推荐使用Flowable。
# Q:是否可以运行到一半手动停止,然后下次继续运行链路?
A:不可以。LiteFlow是一个无状态的规则引擎。不对中间状态进行存储。LiteFlow更希望业务一次性运行完,并且自己保证其幂等性。如果你确实有业务场景,需要运行到一半手动停止。那么建议你去使用Flowable等一些有状态的流程引擎框架。
# Q:为什么规则存储Nacos不支持拆分规则和脚本,而是需要保存整个XML?
因为Nacos没法对一个group进行监听,如果拆分了,那就会导致新增规则,删除规则没法被监听到。
而现在这种单个节点的形式,虽然没拆分,但是功能是齐全的。这也是无奈的选择。我们也想拆分的,但是我们搞不定。
Nacos官方也有类似的issue,官方表示考虑在3.0的时候加入对group的监听特性。
# Q:对于通用组件进行复用编排,上下文类型该如何设置?
如果你有一个通用组件,要定义在不同的链路中。那你就给这个组件一个单独的上下文,LiteFlow是支持多上下文传入的,你调用链路的时候,代入这个上下文。那这个通用组件就可以在不同的链路中使用了。
还有种方法,就是你自己定义一个弱类型的上下文类型,比如Map。但是使用的时候需要你自己去强转类型。
# Q:上下文里的数据是线程安全的吗?
A:LiteFlow虽然提供了默认的上下文实现,但是更建议用户自己去实现自己的上下文。Slot本质上是一个普通的值对象,虽然LiteFlow能保证上下文本身的线程安全(指在多线程情况下,多个请求上下文不会串),但是上下文内数据的线程安全性是无法保障的,这需要用户自己去定义其线程安全的属性。比如你在上下文里定义了一个int的变量,多个异步节点对其进行增加,那当然会有线程安全的问题。你需要在你自己定义的上下文内部去声明一个AtomicInteger
对象,从而保证线程安全。
# Q:LiteFlow性能如何?
A:LiteFlow本身性能优秀,几乎没有什么额外的损耗,在压测过程中,基于复杂的价格逻辑引擎的业务系统,三十多个组件,在实测中可以跑到单机1500多的TPS。当然,这是基于良好的组件实现逻辑的前提下。如果你的组件里有一个bad sql,或者大量的IO操作,RPC调用操作,那么任何框架也无法提升你业务的TPS。这里只能说LiteFlow框架本身对系统几乎无额外损耗,如果你的系统使用了LiteFlow但是TPS/QPS很低的话,那么请从你的组件实现逻辑入手排查。
# Q:是否支持逆向执行,来实现回滚等操作?
A:不支持,如果要实现本地回滚,请用事务来控制,如果涉及分布式事务的回滚,也有分布式事务的解决方案可以用。
但是之后的版本可能会出一个特性,在执行的过程中,如果遇到某个Exception去执行额外的链路,如果真的想逆向执行,可以把回滚组件放到这个里面。
# Q:是否支持界面编排?
A:已经有无数人说的界面编排特性,我想说几句:
界面编排已经不算作特性了,应该算作LiteFlow这个开源框架的一个形态升级,形态延伸。
这个形态升级我一定会做。不仅会做,还会出一整套集编排,管理,监控,追踪于一体的后端界面。
这也是LiteFlow这个框架的愿景:做最轻量,最好用的,能快速赋予生产力的国产优秀的规则编排框架。
LiteFlow才刚刚起步,核心的很多地方还在快速迭代中。后面不做好,无法马上开始做前端编排。加上作者也有本职工作,也是打工人。只能日常挤出时间来做。所以这点望大家理解。目前LiteFlow的迭代还是很频繁的。我打算之后每个月出2个迭代更新版本。
相信这天的到来,不会太久。请支持LiteFlow框架的小伙伴继续关注它。
# Q:如何做跨服务的分布式编排?
A:LiteFlow是轻量级的单服务编排,你可以把它理解为一个工具包。和高可用,分布式没有关系。
你一个业务系统里面有50个组件,liteflow可以编排,复杂一点的也可以。但是你多个业务系统,想要用一个链路,去编排不同服务里的组件。先去调用A服务的组件a,再去调用B服务的组件b,再去调用C服务的组件c,这种LiteFlow并不支持。
变相的实现,只有你独立出来一个服务X,然后服务X写3个组件(x1,x2,x3)分别用rpc去调用a,b,c,然后把x1,x2,x3编排成一个链路。
但是对LiteFlow来说,它运行的组件也只是X服务中的3个组件,至于组件里面是rpc调用还是其他网络IO操作,这和LiteFlow本身没有关系,因为已经涉及到业务实现层了。
# Q:flowExecutor.execute2Resp调用了,为什么取不到上下文中的参数
如下调用
UserContext context = new UserContext();
context.setName("jack");
LiteflowResponse response = flowExecutor.extcute2Resp("chain1", context, UserContext.class);
为什么我在组件或者脚本中取到的name参数为null?
A:在执行器一章里已经有明确的提示了:
//第一个参数为流程ID,第二个参数为流程入参,后面可以传入多个上下文class
public LiteflowResponse execute2Resp(String chainId, Object param, Class<?>... contextBeanClazzArray)
//第一个参数为流程ID,第二个参数为流程入参,后面可以传入多个上下文的Bean
public LiteflowResponse execute2Resp(String chainId, Object param, Object... contextBeanArray)
其中第二个参数为流程入参,流程入参其实和上下文没什么关系,在组件中通过this.getRequestData()
来获得。在脚本中通过requestData
变量获得。
第三个参数为上下文,如果你传入了class,那么liteflow会帮你初始化一个空的对象。当然也支持传入已经初始化好的bean。在组件里通过this.getContextBean
来获得,在脚本里直接通过xxxContext
来引用。
回到上述问题,如果把初始化好的bean作为流程入参传入,而上下文传入UserContext.class,那么其实this.getRequestData
出来的是这个bean,而this.getContextBean
出来是一个空的UserContext对象,所以你拿到的name为null。
这里正确的做法是:
UserContext context = new UserContext();
context.setName("jack");
LiteflowResponse response = flowExecutor.extcute2Resp("chain1", null, context);
在很多情况下,流程入参是可以包装到上下文里去的。所以流程入参这里给个null即可。所以上下文和流程入参是2个完全不相干的概念,这点别弄混淆。
# Q:流程中是否如果有回调该如何处理
例如以下流程包含4个组件
THEN(a, b, c, d)
其中c发送结果到第三方,d要等待第三方回调才可以处理,这种要如何做?
A:LiteFlow是无状态的规则引擎,即时不用LiteFlow,这种模式也应该考虑如何更优雅的设计
一般都是分成2段式,第一段发出去后,保存其中间状态,然后回调回来再进行第二段。
# Q:如果出现栈溢出怎么办
A:确保LF的版本在2.11.4+以上,如果版本没问题,还出现栈溢出,大概率就是jvm参数Xss配置太少了。
解析EL本质上是一个递归调用,如果你层数很多很深,用到的栈空间就会增加。如果Xss太少就会报栈溢出的错误。
# Q:启动时出现NoSuchMethodError的错误是什么原因
在LiteFlow中启动时出现这个错,大概率都可能是以下3个依赖包的冲突而导致。
transmittable-thread-local 要求版本 2.12.3+
byte-buddy 要求版本 1.14.10+
hutool 要求版本 5.8.26+
所谓依赖冲突就是你本地的其他jar包传递依赖的包覆盖了LiteFlow传递依赖的版本。如果你的这个错是以上jar包的某一个,只需要重新定义其版本号即可。