你一定也深有同感,3,数据源广场( 二 )


第二:如何解决数据源依赖
有很多使用场景是一个业务接口需要两个数据源的支持 。 对于依赖 , 抽象出一个依赖解决器 , 它会遍历所有的数据源调用 , 分析调用关系并生成一颗依赖树 。 在调用时 , 对树进行层次遍历和先序遍历 , 保证先执行到无依赖的调用 , 再处理有依赖的调用 。 举例 , 总共需要调用8个数据源分别为A、B、C、D、E、F、G、H , 其中C依赖A , D依赖A和B , E依赖B , G依赖C , F依赖C和D , H依赖E 。 下图表示生成的依赖树:
你一定也深有同感,3,数据源广场
文章图片
如图所示 , 其中先按层次遍历ROOT , 但这是一个虚拟的节点不处理 , 之后调处理A和B , 这里可以并发调用 , 也可以顺序调用 , 交给数据源调用层来处理 。 A和B处理完成后 , 处理A的子节点和B的子节点C、D、F 。 直到所有节点都处理完毕 。
第三:如何映射结果
引擎调用数据源后 , 需要根据表达式来进行结果映射 。 如果是需要自定义返回的每一个key , 比如调用查询 , 默认返回的key为id , 而需要向业务方返回的是vid , 可配置key的值表达式 。 设计时希望表达式尽量简单 , 于是设计出了这样一种表达式 , 比如vid , 可配置为datasource.video.response.id 。
3动态脚本的执行与优化
第一:为什么选择Groovy
因为整体技术栈是Java , 因此首选的脚本语言就是基于JVM , 而选择Groovy一是因为成熟 , 同时语法比Java简洁 , 二是因为接入简单(只需一个jar包)三是因为本身兼容Java的大部分语法 , 学习成本较低 。
第二:Groovy遇到的问题和解决办法
主要是安全问题和性能问题 。 安全的问题非常严重 , 因为脚本是交给用户输入的 , 所以很容易出现风险代码 。 对Groovy的编译器进行了一系列自定义 , 同时使用沙箱 , 将代码进行拦截 , 过滤掉敏感操作 , 最大化避免风险代码的执行 。
性能上 , Groovy的性能远比Java慢 , 于是进行了一番优化 , 比如将Groovy的代码进行预编译和缓存 , 保证执行时不会发生编译动作 , 保证执行一个Groovy单条脚本不会有太大的性能问题 。
第三:最终解决方案
经过 , 发现Groovy本身的执行效率还是要低 , 因为一次请求可能需要执行成百上千次的脚本 , 一次执行的性能问题不明显 , 但是多次执行问题很容易就暴露出来 , 比原生的Java执行仍然有百倍的差距 。
这个既然是Groovy的问题 , 并且无解 , 就想到了是否可以用其它的方式替换Groovy , 于是研究了各种表达式引擎包括Aviator、FEL、MVEL、JSONPath、Java动态编译 。 并且对这些代码进行 , 使用两条语义相同的代码 , 分别编写了不同脚本的版本 , 与Java原生的代码进行比对 。 长时间运行后结果如下:
你一定也深有同感,3,数据源广场
文章图片
上图为两个脚本执行1000次的耗时 , 发现使用Java动态编译和JSON-Path , 性能比Groovy提升了约150倍 。 但是缺点也非常明显:JSON-Path是能写单行的取值语句 , 而Java语法复杂、不方便写内部类和方法等 。 考虑到使用场景 , Java和JSON-Path满足95%以上的场景 , 可再用Groovy写更复杂的脚本 。
稳定性
稳定大于一切 , 接口调用稳定性是重要一环 , 如何保证稳定性呢?1)有问题时要能及时的报警 , 2)为了整个应用的稳定性 , 需要自动熔断 。
1、监控报警
你一定也深有同感,3,数据源广场


推荐阅读