基于LiteFlow构建实时会员权益体系

知识简介:通过LiteFlow规则引擎构建会员权益体系,实现权益节点可插拔,可编排,可复用的特性。完成会员权益数据底盘建设,将分散的权益数据集中,提升权益查询及管理水平。

历史痛点

    1)不同等级权益列表均为硬编码实现,难以做到权益的动态调整。(顺序,增删);

    2)权益迭代由不同的服务及人员开发,数据分散在不同库中,维护困难;

    3)权益领取状态需调用不同服务请求,响应时长不可控,需建设统一的权益查询归属;

    4)权益列表多接口串行查询,性能差。

建设流程

一、搭建实时权益数据底盘

    构建权益底盘表,实时同步权益领取状态。为校验数据准确性,将原数据源信息同步至BDP,T+1校对数据。

二、基于规则引擎编排权益

    基于规则引擎的开源方式、学习成本、社区活跃度、性能与支持度,权益体系综合考虑使用LiteFlow 作为权益节点编排工具。

  1) 为什么要用规则引擎,跟会员权益的契合点在哪里?

    研发角度:

       · 逻辑复杂 顺丰会员根据会员等级,享有不同的权益项,且根据渠道,时间,权益优先级展示不同的权益列表,其中每项权益又需要校验不同的领取规则,要使用大量if-else来实现或者设计模式。但过于复杂的规则逻辑,使用设计模式也往往是存在大量并且关系复杂的类,导致代码难于维护,对新加入的同学极不友好。

       · 变更时需要从头梳理逻辑,在适当的地方进行if...else...代码逻辑调整,耗费大量时间进行梳理。

       · 开发周期较长,需求发生变更时,需要研发人员安排开发周期上线,对于快速变化的业务,传统的开发工作方式显得捉襟见肘。

    产品角度:

       ·  期望能够实现热部署,对于权益的下线和权益的优先级列表,产品期望可配置式的变更。

       ·  降低需求变动的时间成本,快速验证发布。

  2)会员权益继承规则引擎的两大特性

       · 将瀑布流式的代码,转变成以权益组件为核心概念的代码结构,这种结构的好处是可以任意编排,权益组件与组件之间是解耦的,组件之间的流转全靠规则来驱动。

  3)基于规则引擎构建会员权益

      ·  构建权益组件  将会员权益抽象出来,每项权益定义为一个组件,在组件内将当前权益所需结果数据封装至流程上下文中。

       权益类继承NodeComponent,并通过@LiteflowComponent注解标识权益节点并命名。权益节点校验流程:每项权益需进行权益前置校验(是否满足权益展示条件),权益领取校验,之后构建权益返参上下文,组合流程数据。(升级有礼为例)

            

      ·  权益节点编排。根据权益使用场景、会员等级、权益优先级等,构建不同的权益调用链。会员权益编排涉及两大场景,一是会员首页的会员福利模块,展示当前用户待领取及已领取权益。二是各渠道运营位的弹框,增加会员权益的曝光。

       (1)会员福利模块的权益编排:(不同等级用户调用链上权益组件不同,下图为V7等级调用链及权益组件)

        在权益底盘建设前,为提升接口响应效率,采用多权益并行编排。下图为通过XML中配置THEN+WHEN的方式实现调用链配置。

             

        底盘建设完成后,所有权益领取状态在前置节点查询出来,通过上下文传递到各节点,完成结果数据的拼装。

        

                权益列表前端效果展示:

                     

               

              (2)推荐权益编排:跟权益列表需要走完所有权益组件不同,推荐权益在命中后,会直接走到后置节点组件,装配权益文案及图片流程数据后返回。

            下图为通过XML中配置THEN+FINALLY后置节点方式实现V0用户的调用链,接口调用发现生日有礼还未被推荐过时,则直接跳 转到后置节点(下图虚线权益组件将被跳过),完成生日有礼的文案图片配置,将结果数据返回。

          

        推荐权益前端效果展示(APP会员首页运营位)

                                      

注意事项

1) 并行编排 注意使用线程安全的队列

权益列表上线后,每日会有20个左右的空指针(由于异常被捕获和前端兜底,不会对业务造成影响)

排查异常出现在最终列表排序阶段:

       equityVo.getReceiveEquityLists().stream().sorted(Comparator.comparing(ReceiveEquityVO::getIsToReceive,Comparator.reverseOrder()).thenComparing(ReceiveEquityVO::getSort)).collect(Collectors.toList());

本地模拟调用,发现receiveEquityLists中会有空对象出现,将并发模式修改为串行调用则无此现象。观察receiveEquityLists使用ArrayList实现,在并发编排中线程不安全,修改为CopyOnWriteArrayList后问题解决。

故,在使用并行编排时。注意使用线程安全的队列。例如ConcurrentMap,CopyOnWriteArrayList

2) 内存缓存的配置

推荐权益中使用的文案及图片,均在会员配置表中配置,并使用@Cacheable提供本地缓存能力。测试中需要对某项权益图片进行替换,库中更新后,本地缓存较长时间内并未更新成功。查看原有本地缓存配置项:

caffeine.expireAfterAccess=300

caffeine.refreshAfterWrite=300

更新配置为

caffeine.expireAfterWrite =300

caffeine.refreshAfterWrite=300

配置项说明:

expireAfterAccess为访问过期,即有访问则自动续期

expireAfterWrite 当缓存项在指定的时间段内没有更新就会被回收

refreshAfterWrite 当缓存项上一次更新操作之后的多久会被刷新



  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值