全链路营销是去中心化的运营方式,发放精细化的营销权益,打造策略中心系统。根据用户的行为记录用户的喜好商品,通过C端链路的触发实现营销权益发放和权益表达。
当前营销各应用采用TMF框架,中台提供标准节点,营销业务层进行节点编排。全链路营销具有两个链路:数据准备和权益发放。策略中心通过不同的渠道(channelCode)标识不同事件,触发不同的流程编排。
策略中心将不同事件通过不同的渠道进行标识,策略中心的代码架构整体分为4层:接入层、服务层、领域层、基础层。策略实例的驱动逻辑固定,不同玩法对应不同的策略模板,模板会编排不同的节点形成执行器链。
策略中心整体代码流程实现包括行为事件和资源位事件。行为事件代表用户完成了某个行为规则,资源位事件代表用户点击了某个资源位。策略实例的驱动逻辑固定,不同玩法对应不同的策略模板,模板编排不同的节点形成执行器链。
策略域的聚合为TacticsInstanceContext即策略实例,每个策略实例中包含策略活动和相关的执行参数以及执行结果。策略模板是每种玩法对应的配置,提供了核心的流程编排能力。
本文介绍了AE策略中心的技术方案选型与落地实战,从最初版的技术设计到基于事件驱动的流程编排系统的优化和提升。未来可拓展性更强,业务迭代只需增加新的策略模板和节点,符合开闭原则。
本文主要介绍了 AE 策略中心的技术方案选型与落地实战。
全链路营销是去中心化的运营方式,给用户发放精细化的营销权益,
打造策略中心系统
。根据用户的行为记录用户的喜好商品,在满足策略中心规则后,通过 C 端链路的触发实现营销权益发放和权益表达。
当前营销各应用都是采用 TMF 框架,由中台提供标准的节点,营销业务层进行节点编排,每个节点都提供相应的拓展点,可以让不同营销工具实现不同的营销玩法。
上图可以看出营销计算的流程是比较固定的,业务迭代一般在当前流程的节点上进行拓展,TMF 提供的拓展点就是采用策略模式。比如文案构建节点,不同的营销工具需要返回不同的文案,根据营销工具类型匹配文案构建类,执行业务规则。
但是全链路营销面向的是玩法层,所以每次迭代的
业务流程都是不固定的
,对用户的行为要求是不固定的,对下游的依赖也是变化的。所以根据不同的玩法模板,执行不同的业务流程节点,这样做后续的拓展性会比较好。
全链路营销具有两个链路:数据准备和权益发放,数据准备阶段是用户行为规则校验通过后通过 MQ 消息触发,权益发放阶段是在用户在访问某个资源位时,由上游调用策略中心触发
。
用户的每个行为对我们来说都属于事件,只不过有的是同步触发,有的是异步触发,所以依赖不同的事件来编排不同的业务节点,编排方式可以通过配置中心或者 Java 硬编码的形式,拓展性和灵活性更高,整体建设了一个基于事件驱动的流程编排系统。
策略中心将
不同事件通过不同的渠道(channelCode)进行标识
,不同的 channelCode 触发不同的流程编排。
策略中心的代码架构整体分为 4 层:
-
用户的行为校验,由行为规则域统一收敛,满足规则后发送 MQ 消息通知策略中心
-
策略中心整体代码流程实现,如下图所示:
-
行为事件:代表用户完成了某个行为规则,MQ 消息中携带 ruleKey 作为 channelCode,策略中心会通过渠道查询策略活动,构建策略实例,完成数据的准备阶段,包括查询用户操作的商品、算法召回、处理商品折扣等,最后将策略实例的相关数据(商品、流程)存储到 Redis。
-
资源位事件:代表用户点击了某个资源位,API 的入参中有 channelCode,策略中心同样进行活动查询、策略构建,然后从 Redis 中读取数据准备阶段的数据,填充到策略实例,开始进行权益的发放。
设计说明:
策略域的聚合为 TacticsInstanceContext,也就是上文一直提到的策略实例,聚合根是 TacticsActivity 策略活动。每个策略实例 TacticsInstanceContext 中包含一个策略活动和相关的执行参数以及执行结果,执行参数包含买家 ID、渠道、是否加锁、是否仅执行最优策略等信息,所以一个策略活动和一个用户唯一对应一个策略实例。
TacticsInstanceContext 只包含基础的策略执行数据,但是策略层有多个子域,各个子域对 Context 的依赖不同,所以需要对策略实例做能力的拓展,常见的方式有:
我们采用接口拓展的方式解决该问题,因为项目的核心设计思想就是策略 + 工厂模式,可以根据不同的策略模板(templateType)构建不同的 Context。
比如全链路营销 3.0 版本需要用户的商品数据,所以进行接口 IItemContext 的拓展:
每种玩法对应一种策略模板,目前有全链路营销 2.0 和全链路营销 3.0 两个模板,所以通过模板工厂去获取模板的配置:
上图可以看出,getProcessorChain() 提供了
核心的流程编排能力
,因为每个事件对应一个 channelCode,所以流程编排是基于事件标识来完成,代码示例:
public List getProcessorChain(String channelCode) {
List processorChain = Lists.newArrayList();
if ("channelCodeA".equals(channelCode)) {
processorChain.add(QueryacticsProcessor.PROCESSOR_NAME);
processorChain.add(HandleItemPromotionTacticsProcessor.PROCESSOR_NAME);
processorChain.add(EventTacticsProcessor.PROCESSOR_NAME);
} else if ("channelCodeB".equals(channelCode)) {
processorChain.add(CheckEventTacticsProcessor.PROCESSOR_NAME);
processorChain.add(RuleCheckTacticsProcessor.PROCESSOR_NAME);
processorChain.add