美文网首页程序员青春校园
复杂系统的解耦利器,这款可编排组件式引擎,真香!

复杂系统的解耦利器,这款可编排组件式引擎,真香!

作者: 程序员知识圈 | 来源:发表于2021-01-18 14:26 被阅读0次

背景

两年前,公司层面想改造价格系统。公司是做电商业务的,影响商品最终成交价格的因素有很多,各种促销活动的玩法也在不断的加入这个系统。本身这个价格系统代码逻辑古老,新的业务加入,使得原先的逻辑被大量的更改。又经很多人易手。大量的硬代码的分支条件满地跑。这使得代码的阅读十分痛苦,而且改起来难度也高,一不留神,加了一个业务,就把之前的一个业务改坏了。测试起来也痛苦,加了一个小功能,就要对之前的所有的功能进行仔细回归。相信大家在维护老旧系统时也会有此痛苦吧。

这还不是最关键的,公司有一些新的需求需要动态的改变业务的流程顺序,这在老系统根本就没法做了。瀑布流式的逻辑,牵一发动全身。稍微改一下都很费事,还要动态改变逻辑流程?不存在的。

所以系统的改造刻不容缓,当时的想法是,寻找一个开源轻量的解决方案,能够以配置的方式来驱动整个业务逻辑,并能实现热变更。其实这属于流程引擎的范畴,调研了下,发现虽然业界有大名鼎鼎的 FlowableActivitiJBPM 等解决方案,但是都相对比较重,而且集成进整个系统的时间周期也比较长。而轻量级的解决方案,却没找到一个合适的。

所以,就决定动手做一款轻量级的逻辑流程编排引擎。所以,Liteflow 就此产生。并且,Liteflow 从设计之初就是走开源的路线。没有历史包袱,经过 2 年多生产环境的应用,修复和增强之后。Liteflow 如今变得轻量,快速而稳定。承载着多个核心系统的逻辑编排。

作用

Liteflow 就是为解耦复杂逻辑而生,如果你要对复杂业务逻辑进行新写或者重构,用 Liteflow 最合适不过。它是一个轻量,快速的组件式流程引擎框架,组件编排,帮助解耦业务代码,让每一个业务片段都是一个组件。

使用 Liteflow,你需要去把复杂的业务逻辑按代码片段拆分成一个个小组件,并定义一个规则流程配置。这样,所有的组件,就能按照你的规则配置去进行复杂的流转。同时 Liteflow 支持规则文件的热加载,即时完成修改生效。并提供多种持久化规则的方式的扩展。

设计原则

Liteflow 是基于工作台模式进行设计的。何谓工作台模式?

n 个工人按照一定顺序围着一张工作台,按顺序各自生产零件,生产的零件最终能组装成一个机器,每个工人只需要完成自己手中零件的生产,而无需知道其他工人生产的内容。每一个工人生产所需要的资源都从工作台上拿取,如果工作台上有生产所必须的资源,则就进行生产,若是没有,就等到有这个资源。每个工人所做好的零件,也都放在工作台上。

图片

这个模式有几个好处:

  • 每个工人无需和其他工人进行沟通。工人只需要关心自己的工作内容和工作台上的资源。这样就做到了每个工人之间的解耦和无差异性。
  • 即便是工人之间调换位置,工人的工作内容和关心的资源没有任何变化。这样就保证了每个工人的稳定性和业务原子性。
  • 如果是指派某个工人去其他的工作台,工人的工作内容和需要的资源依旧没有任何变化,这样就做到了工人的可复用性。
  • 因为每个工人不需要和其他工人沟通,所以可以在生产任务进行时进行实时工位更改:替换,插入,撤掉一些工人,这样生产任务也能实时的被更改。这样就保证了整个生产任务的灵活性。

这个模式映射到 Liteflow 框架里,工人就是组件,工人坐的顺序就是流程配置,工作台就是上下文,资源就是参数,最终组装的这个机器就是这个业务。正因为有这些特性,所以 Liteflow 能做到统一解耦的组件和灵活的装配。

官网

Liteflow 有自己的官网:

图片

其 Logo 为一个风车形状,其表达的意思是如同风车一般有秩序,稳定而便捷,为你复杂的系统赋能。

Liteflow 托管在 Gitee 上,托管地址为:https://gitee.com/bryan31/liteFlow

有兴趣的小伙伴可以通过托管地址进入官网和示例项目,进行查看。

实战

Liteflow 快速配置

Liteflow 支持了 springboot 的自动装配,当然 Liteflow 也为非 springboot 和非 spring 的项目也提供了支持,这里仅以 springboot 项目为示例进行介绍:

依赖最新的依赖包:

<dependency>
  <groupId>com.yomahub</groupId>
  <artifactId>liteflow-spring-boot-starter</artifactId>
  <version>2.3.3</version>
</dependency>

配置上规则路径:

liteflow.rule-source=config/flow.xml

定义组件

Liteflow 希望用户把复杂逻辑拆分成一个个可复用的组件,所以你得定义你的组件,组件的定义很简单,你需要继承NodeComponent类,然后实现process 方法就行,以下为示例:

@Component("test")
public class TestComponent extends NodeComponent {

 @Override
 public void process() {
  Slot slot = this.getSlot();//slot为这个请求的上下文
  //这里为你的业务处理逻辑
 }
}

这里会有童鞋问,我的业务方法需要入参和出参怎么办,如何传递呢?

Liteflow 为每个线程都自动分配了唯一的一个 slot,可以理解为上下文。想一想上面说的那个模型,每个组件不需要和其他组件进行信息互通,所需要的参数从 slot 里取就是了,这个 slot 就相当于上述模型中的工作台,同时,执行完业务逻辑之后,把结果也放入 slot 里。所以每个组件都是独立的无参构造,这样就消除了每个组件的差异性。

这里的 slot 能贯穿所有组件,每一个组件都可以访问到 slot 里所有的数据。当然每个请求之间的 slot,Liteflow 做了严格的隔离,不用担心数据会串的问题。

Liteflow 提供的默认 Slot 是一个弱类型的对象,这里建议使用者自己定义一个值对象,只需要继承AbsSlot类,便可成为你自己的 Slot。更加贴合业务。

组件除了必须要实现的process 方法,还有几个可选实现:

  • isAccess:表示是否进入该节点,可以用于业务参数的预先判断
  • isContinueOnError:表示出错是否继续往下执行下一个组件,默认为 false
  • isEnd:表示是否立即结束整个流程 ,默认为 false,也可以在业务日志里根据业务判断来调用 this.setIsEnd(true)来结束整个流程。
@Component("test")
public class TestComponent extends NodeComponent {

 @Override
 public void process() {
  Slot slot = this.getSlot();//slot为这个请求的上下文
  //这里为你的业务处理逻辑
 }

  @Override
 public boolean isAccess() {
  Slot slot = this.getSlot();
  //这里做你的参数检查,如果没获取到必须的业务参数,就不会进入该组件
  boolean checkResult = true;//模拟检查结果为true
  return checkResult;
 }

  @Override
 public boolean isContinueOnError() {
  return super.isContinueOnError();//默认为false
 }

  @Override
 public boolean isEnd() {
  return super.isEnd();//默认为false
 }
}

你只需定义你的业务组件,之后,在启动时,Liteflow 会自动扫描到你定义的所有组件,并进行加载。

编辑规则文件

实现完了组件之后,你需要定义规则文件,之前规则文件的路径配置在了config/flow.xml中,所以我们要编辑这个文件。

Liteflow 的规则文件定义非常简单好理解。简单的配置,但是能覆盖大部分的应用场景。

先来看一个示例:

<chain name="chain1">
    <then value="a,c"/> <!-- then表示串行 -->
    <when value="b,d"/> <!-- when表示串行 -->
    <then value="e,f,g"/>
</chain>

在 Liteflow 中,定义了 then 和 when 两种线程执行方式,then 代表串行,上面的示例中,c 必须要等 a 执行完才能执行。when 代表并行,上面的示例中,b,d 同时执行。并且 b,d 都执行完了,下面的 e,f,g 才能挨个顺序执行。

再来看个稍微复杂点的:

<chain name="chain1">
   <then value="a,c(b|d)"/> <!-- c是条件组件,根据cond里的逻辑决定路由到b节点还是d节点,可以配置多个 -->
   <then value="e,f,g"/>
</chain>

Liteflow 提供了条件组件,这种节点的职责就是路由,根据业务逻辑来路由到 b 节点还是 d 节点。

条件组件的定义示例如下,需要去继承NodeCondComponent这个类,最终返回的 b 就是最终要路由到的节点

@Component("c")
public class CComponent extends NodeCondComponent {

 @Override
 public String processCond() throws Exception {
    //你的业务逻辑
  return "b";
 }
}

Liteflow 允许你编辑嵌套的流程,例子如下:

<chain name="chain1">
  <then value="a,c,strategy1,g"/>
</chain>

<chain name="strategy1">
  <then value="m(m1|m2|strategy2)"/>
</chain>

<chain name="strategy2">
  <then value="q,p(p1|p2)"/>
</chain>

在这个例子中,这 3 条链路是串起来执行的,在 xml 里,可以写你的组件 id,也可以写流程 id。配合之前的例子,是不是能表达的流程就更加丰富了点呢。

以上 3 个例子涵盖了 Liteflow 最主要的功能,当然 Liteflow 还提供一些其他的特性,比如如何进行循环执行,如何打印步骤,并且 Liteflow 还提供了一个简易的监控模块,用于统计你的组件执行情况。这里就不一一介绍了。具体你可以点击 Liteflow 的 Gitee 主页进行查看:

https://gitee.com/bryan31/liteFlow

示例工程

为了方便用户的使用,Liteflow 在项目里提供了一个测试用例,你可以直接拿来跑:

图片

同时作者还做了一个带简单业务的示例工程,来演示如何具体实践:

https://gitee.com/bryan31/liteflow-example

这个简单业务是一个电商场景的价格计算的案例,如何通过拆分组件来组合不同的影响价格的业务。并且这个示例工程还提供了一个简单的页面供大家进行调试:

图片

最后

在流程编排开源上,国内一直没有特别著名的开源项目。Liteflow 的体量虽然无法和业界著名的流程引擎相比,但是在某些场景,的确提供了轻量级的解决方案。并且 Liteflow 经过了公司生产大流量业务的考验,在稳定性和性能方面有一定保障。希望 Liteflow 这个开源框架能帮助到有这方面业务需要的同学们。

相关文章

  • 复杂系统的解耦利器,这款可编排组件式引擎,真香!

    背景 两年前,公司层面想改造价格系统。公司是做电商业务的,影响商品最终成交价格的因素有很多,各种促销活动的玩法也在...

  • 高并发架构系列:如何从0到1设计一个MQ消息队列

    消息队列作为系统解耦,流量控制的利器,成为分布式系统核心组件之一。 如果你对消息队列背后的实现原理关注不多,其实了...

  • 从0到1设计一个MQ消息队列

    消息队列作为系统解耦,流量控制的利器,是分布式系统核心组件之一。 了解消息队列背后的实现是非常重要的。 今天,来探...

  • 从0到1设计中间件

    消息队列作为系统解耦,流量控制的利器,是分布式系统核心组件之一。了解消息队列背后的实现是非常重要的。今天,我们就一...

  • 组件化简介

    概念:1.组件化是指解耦复杂系统时将多个功能模块拆分、重组的过程2.把复杂系统拆分成多个组件,分离组件边界和责任,...

  • 规则引擎之新编排思想

    这里介绍一款强大的规则引擎:适用于复杂灵活的业务/规则/流程编排 优点: 在保障解耦和复用的同时,提供了更大的配置...

  • Jetpact 之 LifeCycle

    LifeCycle的诞生: 为了解决代码解耦的问题,将系统组件和普通组件尽可能的解耦 LifeCycle应用: 使...

  • Android-Jetpack-LifeCycle组件的使用

    在软件开发当中,解耦可能是永恒的话题。Android开发当中的解耦体现在系统组件的生命周期和普通组件之间的解耦,L...

  • 实战:消息中间件,解耦、异步、削峰,到底该如何使用

    消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最...

  • 消息队列的概述

    消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步处理,流量削锋等问题,实现高性能,高可用,可伸缩和最...

网友评论

    本文标题:复杂系统的解耦利器,这款可编排组件式引擎,真香!

    本文链接:https://www.haomeiwen.com/subject/cvcxzktx.html