当前位置:网站首页>表达式引擎在转转平台的实践
表达式引擎在转转平台的实践
2022-08-01 10:52:00 【InfoQ】
一、业务背景介绍
二、工程现状
{
"label_红布林标签ID": {
"url": "红布林落地页地址",
"name": "红布林配置",
"其他字段": "省略表示"
},
"uid_帮卖用户ID_searchType_2": {
"url": "转转帮卖暗拍落地页地址",
"name": "转转帮卖暗拍配置",
},
"uid_帮卖用户ID": {
"url": "转转帮卖落地页地址",
"name": "转转帮卖配置",
},
"cateId_图书社会科学分类ID": {
"url": "图书科学类落地页地址",
"name": "图书科学类配置",
},
"cateId_图书自然科学分类ID": {
"url": "图书科学类落地页地址",
"name": "图书科学类配置",
}
}

- 每次新增一种配置维度,需要上线才能完成Key的拼接逻辑和读取逻辑,且读取的优先级硬编码。
- 已有的属性无法自由组合,如转转帮卖暗拍配置的规则为:卖家ID+搜索类型叠加,只能硬编码的方式进行拼接Key,下次的组合维度发生变化还需要开发。
- 相同业务需要维护多条配置,如图书社会科学和自然科学对应的落地页地址都是一个,按照Map的的配置方式需要配置2条、3条、甚至更多。
- 长此以往,Key的拼接和解析逻辑越来越难以维护,配置也越来越庞大。
- 每次上线只是开发拼接Key的逻辑和读取逻辑,都是重复工作,成本高,收益低。
三、方案选型
四、使用表达式引擎重构
4.1 架构设计

4.2 配置重构
[
{
"url": "红布林落地页地址",
"name": "红布林配置",
"ruleEl": "list.contains(labelList, 红布林标签ID)",
"priority": 20,
"其他字段": "省略表示"
},
{
"url": "转转帮卖暗拍落地页地址",
"name": "转转帮卖暗拍配置",
"ruleEl": "帮卖用户ID == product.userId && 2 == product.product.searchType",
"priority": 20
},
{
"url": "转转帮卖落地页地址",
"name": "转转帮卖配置",
"ruleEl": "帮卖用户ID == product.userId",
"priority": 20
},
{
"url": "游戏代练陪玩落地页地址",
"name": "游戏代练陪玩配置",
"ruleEl": "代练分类ID == product.cateId || 陪玩分类ID == product.cateId",
"priority": 20
},
]
4.3 上线小插曲
-XX:+TraceClassLoading[Loaded Script_1645773082560_152/982082822 from com.googlecode.aviator.Expression]
[Loaded Script_1645773082514_151/1163475645 from com.googlecode.aviator.Expression]
com.googlecode.aviator下的ExpressionScript_当前时间戳_一个IDpublic Object execute(final String expression, final Map<String, Object> env,
final boolean cached) {
// 1.编译表达式
Expression compiledExpression = compile(expression, cached);
if (compiledExpression != null) {
return compiledExpression.execute(env);
} else {
throw new ExpressionNotFoundException("Null compiled expression for " + expression);
}
}
public Expression compile(final String expression, final boolean cached) {
if (expression == null || expression.trim().length() == 0) {
throw new CompileExpressionErrorException("Blank expression");
}
if (cached) { // 2.缓存开启与否
FutureTask<Expression> task = this.cacheExpressions.get(expression);
if (task != null) {
return getCompiledExpression(expression, task);
}
task = new FutureTask<Expression>(new Callable<Expression>() {
@Override
public Expression call() throws Exception {
return innerCompile(expression, cached);
}
});
FutureTask<Expression> existedTask = this.cacheExpressions.putIfAbsent(expression, task);
if (existedTask == null) {
existedTask = task;
existedTask.run();
}
return getCompiledExpression(expression, existedTask);
} else {
// 3.实时编译
return innerCompile(expression, cached);
}
}
public ASMCodeGenerator(final AviatorEvaluatorInstance instance,
final AviatorClassLoader classLoader, final OutputStream traceOut, final boolean trace) {
this.classLoader = classLoader;
this.instance = instance;
this.compileEnv = new Env();
this.compileEnv.setInstance(this.instance);
// 上面打印的生成ASM的类名
this.className = "Script_" + System.currentTimeMillis() + "_" + CLASS_COUNTER.getAndIncrement();
// Auto compute frames
this.classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
visitClass();
}
4.4 重构前后对比
- 封装后的组件大量应用到列表页,首页等场景中,动态灵活的规则配置在大促618,双11期间事半功倍。
- 利用表达式内置的函数和自定义函数,避免同类需求多次开发,避免重复造轮子。
- 常规类配置需求,利用表达式引擎基本做到需求变更无上线。
五、总结和感悟
边栏推荐
- 小程序毕设作品之微信美食菜谱小程序毕业设计成品(2)小程序功能
- 如何设计一个分布式 ID 发号器?
- 【cartographer ros】十: 延时和误差分析
- How I secured 70,000 ETH and won a 6 million bug bounty
- URL.createObjectURL、URL.revokeObjectURL、Uint8Array、Blob使用详解
- xss漏洞学习
- 一文说明白ECDSA spec256k1 spec256r1 EdDSA ed25519千丝万缕的关系
- AI篮球裁判火了,走步算得特别准,就问哈登慌不慌
- Android Security and Protection Policy
- 在线GC日志分析工具——GCeasy
猜你喜欢

Mini Program Graduation Works WeChat Food Recipes Mini Program Graduation Design Finished Products (4) Opening Report

Small application project works WeChat gourmet recipes applet graduation design of finished product (1) the development profile

DBPack SQL Tracing 功能及数据加密功能详解

C#/VB.NET convert PPT or PPTX to image
华硕和微星多款产品将升级英特尔Arc A380和A310显卡

小程序毕设作品之微信美食菜谱小程序毕业设计成品(1)开发概要

招聘随想2022

Promise学习(一)Promise是什么?怎么用?回调地狱怎么解决?

Mini Program Graduation Works WeChat Food Recipes Mini Program Graduation Design Finished Products (3) Background Functions

已解决(pip安装库报错)Consider using the-- user option or check the permissions.
随机推荐
7. SAP ABAP OData 服务如何支持 $orderby (排序)操作
Promise学习(四)异步编程的终极解决方案async + await:用同步的方式去写异步代码
正则表达式
【云驻共创】分布式技术之华为云全域调度技术与实践
【cartographer ros】十: 延时和误差分析
线上问题排查常用命令,总结太全了,建议收藏!!
gc的意义和触发条件
Solve vscode input! Unable to quickly generate skeletons (three methods for the new version of vscode to quickly generate skeletons)
What is a stepper motor?40 pictures to show you!
Generate certificates using KeyStore
Flutter Widget 如何启用和屏蔽点击事件
解决vscode输入! 无法快捷生成骨架(新版vscode快速生成骨架的三种方法)
如何解决 chrome 浏览器标签过多无法查看到标题的情况
Mini Program Graduation Works WeChat Food Recipes Mini Program Graduation Design Finished Products (4) Opening Report
pve 删除虚拟机「建议收藏」
【likeshop】回收租凭系统100%开源无加密 商城+回收+租赁
将本地项目推送到远程仓库
Cross-domain network resource file download
【cartographer ros】10: Delay and error analysis
shell--第九章练习