A Scripting Language Based Rule Engine

image.png

Phoebe.png

Scripting language-based rule engine

foreword

In daily development, developers often face such a scenario: business requirements are complicated and constantly changing.

The usual implementation method is to stack code based on if else, which will make developers feel tedious and lack technical content.

Maintaining such code can also be tiresome and confusing.

We consider whether we can provide a solution to separate dynamic business rules from the main process.

Users can write business rules by themselves, and the system converts business rules into code execution, freeing developers from if else.

case

We assume business scenarios

Scenario 1: Financial Risk Control

Scenario 2: Deal Promotion

Combining the above scenarios, we define the characteristics of the business model:

  • Has fixed input parameters and output formats
  • The intermediate rules are required to be configurable and as flexible as possible

demand model

Regular Data Model

We abstracted the data model of the business scenario

We decompose the rules into variables + conditions + results, so that the business rules and the implementation code can be converted into each other.

system model

We simply divide the system into two modules: rule executor and rule management.

  • rule executor

    It is responsible for selecting the rule object to be executed (including the execution order of the rules), parsing and executing, and returning the final result.

  • rule management

    Open to development and business, responsible for the structured analysis and exchange of business rules and implementation codes.

accomplish

We divide the system into the following levels to achieve:

The execution of dynamic code scripts requires a scripting language executor.

The mutual conversion between business rules and code scripts requires structuring the business rules data.

In addition, the ability for business parties to define their own required algorithms in the system and entrust the system to execute is also necessary.

scripting language executor

In the JVM environment, the scripting language can choose Groovy, Scala, JRuby and so on. This solution adopts another method, which is implemented by borrowing Ali's open source tool QLExpress .

For Groovy and QLExpress, we have some feature comparisons

execution engine execution type expression language performance characteristic
Groovy compiled support high java syntax compatible
QLExpress interpretive support high Strong function expansion

According to the survey results, what we need is an engine that supports expression language, is lightweight, flexible, and has strong function extensibility.

So we choose QLExpress.

In addition to the features mentioned above, QLExpress also

  • 能绑定 java 类或者对象的 method 并且在脚本中执行
  • 可以自定义扩展操作符
  • 支持集合类参数
  • 与 spring 无缝集成

这些特性都是我们实现规则引擎的必要的条件

QLExpress 的执行方式:

ExpressRunner runner = new ExpressRunner();
// 业务的上下文参数
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
context.put("a", 1);
context.put("b", 2);
context.put("c", 3);
// 规则脚本
String express = "a + b * c";
// 规则结果
Object r = runner.execute(express, context, null, true, false);
System.out.println(r);
复制代码

业务对接系统只需要:

  1. 提供上下文参数(这些参数是一般不会变化)
  2. 处理规则结果返回

如此,我们做到了将业务流程与业务规则分离,开发人员通过服务调用的方式,将大量业务逻辑交由规则引擎系统处理。

数据结构化

根据定义规则的数据模型,我们将规则拆分为变量,条件,结果三个维度。

简单条件,可以由变量和逻辑运算符组成;规则的条件也可以由多个简单条件组合而成。规则结果也可以由变量来表示。

变量的来源可以是业务提供的上下文参数,可以是定义的一套算法,算法需要支持业务使用方自定义。

我们用一个例子来解释这些概念吧。

有一个交易订单的业务,在用户下单操作后,希望用户同时满足条件

  • 用户所在地为A市
  • 用户没有购买过当前商品
  • 下单时间为晚上

时,希望给当前订单8折优惠。

我们将下单业务的输入参数简单定义为:用户 ID ,商品 ID 。为了构造规则条件,我们还需要定义一些中间变量。

  • 变量1 = 根据用户 ID 获取用户所在地
  • 变量2 = 根据用户 ID 和商品 ID 获取用户购买记录
  • 变量3 = 判断当前时间为晚上

有了三个变量作为条件,我们可以再定义:变量4 = 8折,作为最终返回结果。

因此这个规则可以等价为:

if 变量1等于A市 并且 变量2等于0 并且 变量3等于 true

​ return 变量4

因此,我们将一条具体的业务规则转换成了对一条逻辑关系记录和若干变量的管理。

实现了数据的结构化。

定义绑定方法

在业务规则需求场景中,编码的实现过程通常是使用上下文参数或者通过参数进行计算后产生的临时变量作为规则的组成要素,参与规则的业务逻辑运算。

因此需要业务能将自定义的方法预先注册进脚本执行器,脚本执行器在执行到相关的代码时候,能够调用方法,得到业务结果。

我们通过 QLExpress 绑定java类或者对象 method 的特性,将业务方法注册进 QLExpress 执行器。

public void functionABC(Long a,Integer b,String c){
	System.out.println("functionABC");
}
    
    
ExpressRunner runner = new ExpressRunner();
runner.addFunctionOfServiceMethod("abc", singleton,"functionABC",new Class[]{Long.class,Integer.class,String.class},null);
String exp = "abc(a,b,c)";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("a",1L);
context.put("b",2);
context.put("c","3");
runner.execute(exp, context, null, false, false);
}
复制代码

QLExpress执行绑定java类对象方法的底层逻辑与java程序中调用是一样的,所以我们也可以绑定远程方法。

我们知道,dubbo可以做到*像调用本地方法一样调用远程服务,*因此我们能将绑定什么样的方法的决定权交给业务,增加方案的开放度。

总结

本文提供了一个针对规则类需求的一套轻量级解决方案。

将规则需求数据进行结构化解析,然后转换成脚本语言,通过执行脚本语言实现业务规则需求。

这套方案能够在满足业务主体流程稳定的同时,通过提供一定程度的扩展能力,满足业务规则灵活变化的需要。目前已经在政采云的商家交易和报销费控业务中得到了应用。

展望未来

在业务间的需求差异巨大的背景下,如何在满足业务的灵活定制的同时,又能将能力扩展为通用服务,节省开发成本,需要在后续的迭代中逐步完善。

目前规则逻辑只支持单一路径,后面可以考虑多条路径甚至路径嵌套规则的实现。

规则执行器在执行规则脚本的过程中,如何优化其中间变量,也是可以优化的方向。

未来会继续从技术及业务两方面入手,将系统建设的更加易用、高效。

推荐阅读

JVM系列文章第二章-类文件到虚拟机

Dapr 实战(一)

Dapr 实战(二)

DS 版本控制核心原理揭秘

DS 2.0 时代 API 操作姿势

招贤纳士

Zhengcaiyun technical team (Zero), a team full of passion, creativity and execution, Base is located in the picturesque Hangzhou. The team currently has more than 300 R&D partners, including "veteran" soldiers from Ali, Huawei, and NetEase, as well as newcomers from Zhejiang University, University of Science and Technology of China, Hangdian University and other schools. In addition to daily business development, the team also conducts technical exploration and practice in the fields of cloud native, blockchain, artificial intelligence, low-code platform, middleware, big data, material system, engineering platform, performance experience, visualization, etc. And landed a series of internal technology products, and continued to explore new boundaries of technology. In addition, the team has also devoted themselves to community building. Currently, they are contributors to many excellent open source communities such as google flutter, scikit-learn, Apache Dubbo, Apache Rocketmq, Apache Pulsar, CNCF Dapr, Apache DolphinScheduler, alibaba Seata, etc. If you want to change, you have been tossed with things, and you want to start tossing things; if you want to change, you have been told that you need more ideas, but you can't break the game; if you want to change, you have the ability to do that, but you don't need you; if you If you want to change what you want to do, you need a team to support it, but there is no place for you to lead people; if you want to change, you have a good understanding, but there is always that layer of blurry paper... If you believe in the power of belief, I believe that ordinary people can achieve extraordinary things, and I believe that they can meet a better self. If you want to participate in the process of taking off with the business, and personally promote the growth of a technical team with in-depth business understanding, a sound technical system, technology creating value, and spillover influence, I think we should talk. Anytime, waiting for you to write something, send it to [email protected]

WeChat public account

The article is released simultaneously, the public account of the technical team of Zhengcaiyun, welcome to pay attention

image.png

Guess you like

Origin juejin.im/post/7078456167797620766