一、背景
推荐系统一般可以抽象为下面几个核心的流程:
资源加载(用户画像、用户历史、ab实验集等)召回融合过滤(负反馈、运营等)排序重排
而每个流程都可能会设置大量的策略实验,以选取最优策略全量发布,以提高用户点击率等指标。在一点内部,整个推荐系统分为了若干微服务,主要的服务如下图所示,其中召回层、策略层、融合层有很多公共的逻辑,这些层中每个服务都有资源加载、召回(从下游获取数据)、融合、过滤、排序等流程。
由于很早之前的老服务没有抽象出业务模型,很多服务实际上流程是一致的,如果模型合理,不需要分开,而且代码冗余问题比较严重。另一方面,老服务项目代码中的条件逻辑有90%都是硬编码,导致修改很多逻辑的修改都需要上线,周期较长,无法支撑策略的快速迭代。
因此,一点内部开发了策略执行平台(Hermes),进行快速策略迭代。Hermes不仅仅适用于推荐的场景,因为目前只有推荐场景接入,所以本文均使用推荐相关的概念来介绍该平台。Hermes推荐策略平台不仅包括策略执行引擎、策略配置服务等模块,还提供了大量基于Hermes的组件,用于一站式开发,从而降低开发难度,提高开发效率。
二、设计方案
2.1设计思路
策略执行引擎是策略平台的核心组件,而执行引擎的核心则是一个责任链。在责任链实现方面,首先排除了开源工作流组件,工作流场景更看重的是在上下游存在较强依赖关系的基础上做流转控制,甚至支持事务,而且其中大量代码用来支持在配置文件比如xml中配置流程。而推荐服务场景,是一个数据流漏斗,而且只会往前走不存在回滚。为了支持快速迭代,策略配置的修改就需要实时生效,因此开发配套的策略配置平台。
本文的策略平台主要有以下设计点:
策略组成与结构串行、并行控制动态条件策略执行上下文执行责任链策略配置读取、构建、实时同步
2.2基本概念
Hermes的基本概念有:策略(strategy)、子策略(subStrategy)、层(layer)、执行单元(processor)和执行单元组(processorGroup)。子策略、层、执行单元(组)都可以通过配置动态地创建、修改、组合与编排。
执行单元
用户请求执行流程当中最小粒度的业务处理单元,叫做“执行单元”,比如一个召回或者一个过滤器。在策略引擎执行过程中,会有一个执行上下文对象(context对象)传给所有执行单元,来进行数据读写。执行单元属性有:
名称:前端属性,不影响执行;所属层:表达从属关系;所属执行单元组:表达从属关系,可选;Java全限定类名:实现指定接口,用于创建processor实例;初始化参数:也叫构造函数参数,用于创建processor实例;执行顺序(优先级):一个数值,表示同一个执行链中processor执行的先后顺序,数值越小顺序越靠前;若所属组设置了“互斥”,则当前字段值表示优先级,数值越大优先级越大;执行方式:直接执行、同步阻塞(可设置超时时间);多个顺序相同且同步阻塞执行的processor会并发执行,超时时间以其中最长的时间为准;执行条件:根据上下文context判断是否执行当前执行单元。
执行单元组
一个执行单元组由多个“执行单元”或者“组”组成。“执行单元组”是是树形结构,叶子节点都是“执行单元”,中间节点为“子执行单元组”。执行单元组的属性有:
名称:前端属性,不影响执行;所属层:表达从属关系;所属组:父节点,表达从属关系,可选;顺序:一个数值,用来生成执行链中执行单元的执行顺序,数值越小顺序越靠前;若所属组设置了“互斥”,则当前字段值表示优先级,数值越大优先级越大;条件:根据上下文context判断是否命中当前组;是否互斥:互斥时同一个组里命中条件的执行单元(组)只会执行一个,优先执行优先级更大的,若优先级相同则以执行单元(组)创建时间先后为准。
层
多个功能类似的执行单元可以组合成一个“层”,比如多个召回构成“召回层”。推荐中各个流程的执行顺序是相对固定的,比如召回层位于排序层之前,“层”是一个虚拟的概念,只会在配置后台的前端页面上看到,用于执行单元功能的划分,而对策略执行引擎是不可见的。“层”只有“名称”和“顺序”两个属性,策略执行引擎读取的策略配置中,执行单元的顺序由“层”顺序、“组”顺序和原“执行单元”顺序生成,从而对引擎隐藏“层”的概念。
子策略
多个层组成一条“子策略”。子策略是执行链的最小单位,执行单元接口有“intercept”和“process”两个方法,分别表示拦截和执行。
子策略执行链结构如下图所示,执行单元先后顺序为A→B→C→D,执行顺序为Di→Ci→Bi→Ai→Ap→Bp→Cp→Dp,如果“intercept”方法返回true,则跳过剩下的执行单元,直接执行当前执行单元的“process”方法,比如Ci返回true,则执行顺序为Di→Ci→Cp→Dp。
“intercept”可以应用在缓存的场景,比如执行单元C表示“返回结果封装”,Ci表示“从缓存中取数据集”,命中缓存则返回true,未命中缓存则返回false,继续执行A、B,获取候选数据集。
子策略属性有:
名称:前端属性,不影响执行;所属策略:表达从属关系;执行顺序:一个数值,表示同一个执行链中子策略执行的先后顺序(子策略执行链由多个执行单元链组成,子策略接口中只有“process”方法,纯单向链表结构),数值越小顺序越靠前;执行方式:直接执行、同步阻塞(可设置超时时间);多个顺序相同且同步阻塞执行的子策略会并发执行,超时时间以其中最长的时间为准;执行条件:根据上下文context判断是否执行当前子策略。
策略
“策略”由一条或多条子策略组成,结构为树形。策略有3种类型:资源加载(resourceLoader)、主策略和fallback策略,“资源加载”过程主要是解析请求参数、加载用户数据等操作,当主策略执行抛出异常或者满足一定条件触发fallback时,会执行fallback策略,以填补主策略执行结果。
策略属性有:
名称:前端属性,不影响执行;fallback策略:每个策略可绑定多个fallback策略;优先级:一个数值,表示优先级,数值越大优先级越大;执行条件:根据上下文context判断是否执行当前策略,一次请求只会执行一条主策略,命中多个主策略则执行优先级最高的。
一条完整的策略如下图所示:
2.3框架设计
Hermes策略执行引擎,架构特点是“模块化、低耦合、快速反应”,主要分为配置同步、策略中心、执行单元池、线程池和任务中心五个模块。Hermes策略引擎使用Drools规则引擎(
转载请注明:http://www.0431gb208.com/sjszlff/1198.html