16

闲鱼的实时触达系统是如何玩转跨端开发的?

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzU4MDUxOTI5NA%3D%3D&%3Bmid=2247486291&%3Bidx=1&%3Bsn=14f7377a5f88a942b165993a66555f25
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在Omega实时触达系统的系列技术文章中,已经对 行为采集中心 CEP规则中心 用户触达中心 三个子系统进行了详细介绍。闲鱼定义了自己的DSL语言(领域特定语言),它把复杂的代码开发转换成了一种类SQL形式的简练表达,而在底层具体实现上,端侧、前端和云端可以使用的不同高级语言,如:python、c++、javascript、java等。使用DSL的表达方式这样降低了不仅可以降低技术门槛,还提升了研发效率这就带来了本文所要介绍的问题:如何实现自定义DSL语言到多种底层高级语言的翻译?

DSL语言翻译中遇到的问题

Omega系统中不仅实现了云端的复杂事件计算(CEP)引擎,端侧和前端也实现了各自的复杂事件计算引擎,相较于云端可以计算跨用户行为,端侧和前端CEP则更关注于单用户行为的计算,其更加实时和安全。因为各端CEP计算引擎的实现差异,导致了开发人员只能局限在各自领域内做开发,对于跨端开发有较高的技术门槛,另外时间成本也会不可控。因此,我们提出用自定义DSL语言来屏蔽各端的技术差异,在理想的情况下,开发人员应该只关注业务逻辑,其他技术细节不应该花费精力,如下图所示红色部分。

AfiAjqA.jpg!mobile

各端CEP计算引擎在实现上的技术差异主要包括输入数据、CEP计算API、执行容器、结果输出等。在输入数据方面,由于端侧、前端和云端处理的输入数据是有差异的,如:端侧/前端可以处理用户在某个页面停留5s的数据,而云端无法感知,这就要求自定义DSL语言必须在数据输入层面兼容各端输入数据的差异;在CEP计算API方面,各端设计的CEP计算基础API可以是不同的,如:i=i+1和i++,没有统一的一套协议规范很容易导致横行野蛮扩张,还会增加后期统一翻译的难度;在执行容器方面,端侧和前端是在阿里的端计算容器Walle上计算,云端则是在阿里的流计算容器blink上计算;在结果输出方面,由于各端对应的是同一个用户触达中心,在计算结果协议上各端基本是一致的。在明确了各端之间的差异之后,可以梳理出以下几部分核心内容:

输入数据协议:兼容各端输入数据的差异;

CEP计算API:便于统一翻译的实现和基础协议的管控;

翻译框架选型及翻译:兼容各端高级语言的翻译工作,便于统一各端的能力升级迭代;

屏蔽执行容器差异:解决执行容器和各端CEP计算引擎的映射关系;

DSL语言翻译的设计实现

输入数据的统一

对于各端输入数据的差异,业界比较通用的做法是,构建一层通用数据模版层来屏蔽各端输入数据的差异,各端根据需要注册自己的输入数据实例。这样做的好处是自定义DSL语言的输入可以统一起来,在后续翻译到各端语言的过程中,再根据已注册的符合模版规范的各端具体实例进行转换。我们也采用了这种方式来处理各端输入数据的差异,如下是我们定义的输入数据协议模版:

{
    "eventAlias":"事件别名",
    "eventCode":"PUBLISH_ITEM",
    "eventDesc":"卖家的详情被浏览",
    "eventTime":"事件发生时间",
    "updateTime":"事件更新时间",
    "partitionId":"分区id",
    "userId":"用户id",
    "extraInfo":{
        "itemId":"商品id",
        "buyerId":"买家id",
        "sellerId":"卖家id",
        "itemType":"商品类型",
        "itemStatus":"商品状态",
        "categoryId":"类目id",
        "latitude":"经度",
        "longitude":"纬度",
          ...:...
    },
    "scene":"场景",
    "fromScene":"上一个场景",
    "toScene":"下一个场景",
    "isFirstEnter":"是否首次进入",
      "bizId":"唯一Id",
    "sessionId":"会话id",
    "actionType":"行为类型",
    "actionName":"行为标识",
    "ownerName":"骆彬"
}

CEP计算API的统一

对于各端CEP计算API的统一,业界比较成熟的协议规范是Flink CEP的协议规范,其基础计算API拆分的更加合理,各端的接受度更高。因此,我们以Flink CEP的协议规范为基础,定义了一套闲鱼CEP计算引擎通用的计算API协议规范,各端根据协议去实现具体的API即可,协议规范如下所示:

public static <X> Pattern<X, X> begin(final String name); 
public Pattern<T, F> where(IterativeCondition<F> condition);
public Pattern<T, F> or(IterativeCondition<F> condition);
public Pattern<T, F> until(IterativeCondition<F> untilCondition);
public Pattern<T, F> within(Time windowTime);
public Pattern<T, T> next(final String name);
public Pattern<T, T> notNext(final String name);
public Pattern<T, T> followedBy(final String name);
public Pattern<T, T> notFollowedBy(final String name);
public Pattern<T, T> followedByAny(final String name);
public Pattern<T, F> times(int times);
public Pattern<T, F> allowCombinations();
public Pattern<T, F> consecutive();
public static <T, F extends T> GroupPattern<T, F> begin(Pattern<T, F> group);
public GroupPattern<T, F> next(Pattern<T, F> group);

翻译框架及实现

在统一了输入数据和CEP计算API之后,就可以开始自定义DSL语言到统一的CEP计算API的翻译设计。由于CEP计算引擎有各端的实现,使得翻译框架必须能够支持多种目标语言的翻译。目前业界使用的较多的翻译框架有Antlr V4、parboiled、Apache Calcite,其各自的特点如下表所示:

jMFz2en.png!mobile

结合以上各种翻译框架的特点,Antlr V4的翻译框架可以友好的支持我们对于多种语言翻译的需求,且开发更为方便,最终我们选择了Antlr V4的翻译框架。根据自定义DSL语法和统一的CEP计算API,可以设计一套语法解析文件,然后由Antlr V4生成DSL语法解析器和AST语法树,最后,结合各端特点完成由AST树节点到高级语言的翻译,大致流程如下图所示:

n6rIzuN.jpg!mobile

执行容器的屏蔽

对于执行容器与各端CEP计算引擎之间一对多的映射关系,我们添加了一个DSL规则类型的概念。使用DSL规则类型去关联相应的执行容器,进而屏蔽了开发人员对于底层执行容器的感知。另外,我们设计了DSL编辑器,并提供了语法和事件提示、审核流、资源管理、结果查询等辅助功能,相信会给开发人员提供一个友好的体验。

RZJ7FnN.png!mobile

实际应用效果

目前Omega的翻译方案经过双十一实践的检验,在降低技术门槛和提高开发效率方面效果显著。通过自定义DSL语言屏蔽各端语言实现的差异性,使得稍有SQL使用经验的人都可以快速进入开发,开发的技术门槛直线下降,开发人员可以专注于业务逻辑的实现。经过双十一活动的实践,通过自定义DSL语言开发业务规则可以把之前一周的开发量压缩到1-2个小时,平均开发一个DSL业务规则耗时在10分钟左右,开发效率成倍提升。

qeEnMfz.jpg!mobile

后续开发计划

Omega的开发生态已经具备了一定规模,输出了一系列核心协议标准,提供了简洁、高效的集成开发和运维环境。目前,端侧和云端已经接入,后续要还要接入前端,向更广的领域发展,对于各端翻译的技术细节后面也会详细介绍。另外,基于翻译器的核心协议标准,进一步深化闲鱼DSL语言能力,对外输出协议标准和成熟的翻译器产品也在规划之列。

RJ3aeiB.png!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK