程序员的保命技能——流程编排,你一定要了解!

后端

作为一个优秀的程序员,要守住职业的底线。能简单快速的完成的一件事,就一定要用简单的方案快速完成。不可过度的设计,始终保持系统的简洁!

曾几何时,我对于流程编排这件事 嗤之以鼻,为什么呢?我认为流程编排是典型地过度设计。

在我看来,代码越直观越可靠,我不喜欢看代码的时候跳来跳去。但是流程编排后,要把各个方法放到扩展类,通过组合各个扩展类新建一个流程,实现业务功能,这能有什么好处呢?

直到我来到一个中台团队,才意识到流程编排能力是保命的能力。

业务中台要接入很多的业务方,每个业务方并不是完全相同。很多时候无法完全复用,需要改造系统适应新的业务。

新增业务代码时,务必要保证原有业务不受影响,如果没有流程编排能力,就会充斥大量的 if else 。


if (biz == BizA || biz == BizB) {
     //do some thing
     //这部分逻辑相同
     if (biz == BizA) {
         //差异化处理
     }
     
     if(biz == BizB) {
        //差异化逻辑
     }
}

例如上面的代码,不同的业务线若有差异化逻辑,需要新增分支单独处理。想象一下,当有 10 多个业务接入了你的系统,那么一定让人抓狂……

任何一个人都无法保证对 10 多种业务完全熟悉,每个人可能只负责 1 个业务,然而如果没有代码逻辑的隔离,维护者只能在千丝万缕中,才能找到目标代码逻辑。更可怕的是,每次新增一个业务,需要在原有的屎山中继续💩,不断新增 if else。直到有一天,有一个倒霉蛋改错了代码,导致其他重要业务受影响,引发线上故障。

想象一下,当你改了几行代码以后,要求测试同学,回归10 多个业务线的全部逻辑?这显然不现实。

以上的问题和痛点可归纳为:代码隔离性和业务扩展点问题。解决这两类问题有如下手段!

  1. 使用流程引擎,为不同的业务配置不同的流程执行链
  2. 使用插件扩展引擎,不同的业务实现差异化部分。

MemberClub 中大量使用流程引擎和插件扩展引擎解决业务隔离性和扩展性 问题。

MemberClub是托管在Gitee平台的开源项目,提供了付费会员的交易解决方案,在各类购买场景下提供各类会员形态的履约及售后结算能力,具体介绍可参见 gitee.com/juejinwuyan…

配置流程执行链

考虑到不同的会员产品交易提单流程不同,不同的产品应配置不同的流程,DemoMemberPurchaseExtension 实现了购买扩展点,并且定义了三个流程执行链的配置方式。如截图所示~ picture.image

看新机会

如果近期看新机会,不排斥偶尔加班(加班给加班费)可以考虑下,薪酬money给的还可以:技术大厂,前、后端/测试捞人,一起来共事~

定义流程节点

流程节点中的方法包括 process、success、rollback和 callback方法。

picture.image

流程执行

流程执行时 需提供流程上下文对象。调用 FlowChain.execute 方法即可

picture.image

实际执行阶段,各个流程节点被流程引擎串联起来依次执行,类似于责任链的设计模式,具体执行顺序如下图所示。 依次执行每个流程节点的 process 方法,若 process 方法出现异常,则执行 rollback 方法。若所有的 process 方法执行成功,则倒序依次执行 success方法。

picture.image

流程引擎执行原理

以下是 FlowChain.execute方法执行原理。代码位置

public <T> void execute(FlowChain<T> chain, T context) {
    Exception exception = null;
    int index = -1;
    for (FlowNode<T> node : chain.getNodes()) {
        try {
            node.process(context);
            index++;
        } catch (Exception e) {
            if (e instanceof SkipException) {
                CommonLog.warn("当前流程:{} 发出 Skip请求,后续流程不再执行", node.getClass().getSimpleName());
                break;
            }
            exception = e;
            break;
        }
    }

    if (exception != null) {
        for (int i = index; i >= 0; i--) {
            FlowNode<T> node = chain.getNodes().get(i);
            try {
                node.rollback(context, exception);
            } catch (Exception e) {
                CommonLog.error("rollback执行异常,忽略 name:{}", node.getClass().getSimpleName(), e);
            }
        }
    } else {
        for (int i = index; i >= 0; i--) {
            FlowNode<T> node = chain.getNodes().get(i);
            try {
                node.success(context);
            } catch (Exception e) {
                CommonLog.error("success 执行异常,忽略 name:{}", node.getClass().getSimpleName(), e);
            }
        }
    }

    for (int i = index; i >= 0; i--) {
        FlowNode<T> node = chain.getNodes().get(i);
        try {
            node.callback(context, exception);
        } catch (Exception e) {
            CommonLog.error("callback执行异常,忽略 name:{}", node.getClass().getSimpleName(), e);
        }
    }
    if (exception != null) {
        throw exception;
    }
}

以上全部代码地址 可以参见 MemberClub 代码位置

我的开源项目

最后夹带一点私货,五阳最近花了3个月的时间完成一个开源项目。

开源3周以来,已有近 230 多个关注和Fork

Gitee:gitee.com/juejinwuyan…

GitHub github.com/juejin-wuya…

开源平台上有很多在线商城系统,功能很全,很完善,关注者众多,然而实际业务场景非常复杂和多样化,开源的在线商城系统很难完全匹配实际业务,广泛的痛点是

  • 功能堆砌,大部分功能用不上,需要大量裁剪;
  • 逻辑差异点较多,需要大量修改;
  • 功能之间耦合,难以独立替换某个功能。

由于技术中间件功能诉求较为一致,使用者无需过多定制化,技术中间件开源项目以上的痛点不明显,然而电商交易等业务系统虽然通用性较多,但各行业各产品的业务差异化极大,所以导致以上痛点比较明显

所以我在思考,有没有一个开源系统,能提供电商交易的基础能力,能让开发者搭积木的方式,快速搭建一个完全契合自己业务的新系统呢?

  • 他们可以通过编排和配置选择自己需要的功能,而无需在一个现成的开源系统上进行裁剪
  • 他们可以轻松的新增扩展业务的差异化逻辑,不需要阅读然后修改原有的系统代码!
  • 他们可以轻松的替换掉他们认为垃圾的、多余的系统组件,而不需要考虑其他功能是否会收到影响

开发者们,可以择需选择需要的能力组件,组件中差异化的部分有插件扩展点能轻松扩展。或者能支持开发者快速的重新写一个完全适合自己的新组件然后编排注册到系统中?

memberclub 就是基于这样的想法而设计的。 它的定位是电商类交易系统工具箱, 以SDK方式对外提供通用的交易能力,能让开发者像搭积木方式,从0到1,快速构建一个新的电商交易系统!

picture.image

具体介绍可参见

Gitee开源地址gitee.com/juejinwuyan…

GitHub开源地址 : github.com/juejin-wuya…

在这个项目中你可以学习到 SpringBoot 集成 以下框架或组件。

  1. Mybatis、Mybatis-plus 集成多数据源

  2. Sharding-jdbc 多数据源分库分表

  3. redis/redisson 缓存

  4. Apollo 分布式配置中心

  5. Spring Cloud 微服务全家桶

  6. RabbitMq 消息队列

  7. H2 内存数据库

  8. Swagger + Lombok + MapStruct

同时你也可以学习到以下组件的实现原理

  1. 流程引擎的实现原理

  2. 扩展点引擎实现原理

  3. 分布式重试组件实现原理

  4. 通用日志组件实现原理 参考:juejin.cn/post/740727…

  5. 商品库存实现原理: 参考:juejin.cn/post/731377…

  6. 分布式锁组件: 参考:

  7. Redis Lua的使用

  8. Spring 上下文工具类 参考: juejin.cn/post/746927…

——转载自作者:五阳

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
云原生数仓如何构建高性能向量检索技术
火山引擎ByteHouse团队基于社区 ClickHouse 进行技术演进,提出了全新的向量检索功能设计思路,满足业务对向量检索稳定性与性能方面的需求。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论