Moment For Technology

Research and Thinking on Rules Engine (I)

Posted on Aug. 8, 2022, 8:31 p.m. by Todd Payne
Category: The back-end Tag: The back-end architecture

1. Rule engine description

There are rules for everything in the world

Speaking of rule engine, I believe many partners have many questions about rule engine. What is it? What can it do? What should be done? Hope to give you some inspiration by reading the following.

First of all, what is the rule engine? Let's see how Baidu Baike defines it

A rule engine, developed from an inference engine, is a component embedded in an application that enables business decisions to be separated from application code and written using predefined semantic modules. Accept data input, interpret business rules, and make business decisions based on business rules.

What a rules engine does is input certain judgment logic and use that input data to make decisions

Rules engine so good? Is a rules engine a good fit for our business?

First, we have a basic pros and cons analysis:

Benefits of the rules engine:

  1. High flexibility

    The immediate effect of this flexibility is to shorten the development to live time and fix bugs with hot updates

  2. Natural componentization

    Simplify complex business logic, reduce the amount of business code, easy to manage business logic.

Disadvantages of rules engines:

  1. Additional service dependencies were introduced

    For some scenarios with high requirements on stability and correctness, it is not recommended to introduce them in the early stage (perfect permission control and rule unit testing ability should be provided).

  2. Increase product and technology learning costs in the early stage

    The product needs to have a certain abstract thinking, and the variable part of the system is given in the requirements document for abstract processing

    Research and development requires learning part of the rule syntax, and understanding system implementation and constraints

  3. Rule hot update cannot be relied on to satisfy all business decision scenarios

Therefore, the rule engine is not a panacea. On the premise of being familiar with the specific capabilities of the rule engine, determine whether it can achieve the highest benefits according to the specific business scenarios

2. Select a rule engine

Rules engine/metrics drools gengine
To fit the difficulty There is a threshold easy
Operation mode Only the sequential type is supported Supports sequential, parallel, and N-M modes
Development of language java golang
Community activity high general

Based on my level, GENGine, which is easier to learn, has been selected as the research object here (although rules engines have different operating modes and languages, there is no difference to our understanding of the essence).

  • Gengine is a rules engine based on Golang and AST(Abstract Syntax Tree), and the syntax supported by Gengine is a custom DSL
  • Gengine was licensed open source by Bilibili.com in July 2020
  • Gengine has been used in a number of business scenarios such as station B risk control system, traffic delivery system, AB testing and recommendation platform system
  • You can also apply Gengine to any business scenario that requires rules or metrics support for Golang applications

Gengine rule engine usage process

Partial rule patterns are supported

The operation mode The method name meaning
Order type ExecuteSelectedRulesWithControlAndStopTag Execution by rule priority (from top to bottom)- Time is the sum of all rule execution times
And hair ExecuteSelectedRulesConcurrent All rules are executed concurrently (with the longest execution time - consider pool limits)
Mixed mode ExecuteSelectedRulesMixModel Execute one rule with the highest priority, and then execute all the remaining rules concurrently
N-M ExecuteNConcurrentMConcurrent The first N rules are executed concurrently, and M rules are executed concurrently/The first N rules are executed in sequence, and M rules are executed concurrently
  1. Methods to rely on in making rules (hard coding)

    type ruleResponse struct {
      Code int
      Data map[string]interface{}}func success(code int) ruleResponse {
      return ruleResponse{
        Code: code,
        Data: make(map[string]interface{},}}func (rule ruleResponse) AddDataParam(name string, value interface{}) {
      rule.Data[name] = value
    }
    Copy the code

    Custom functions and structs are not supported in the rules. When non-int, string and bool values need to be returned, we need to inject corresponding implementation methods externally for invocation within the rules (such as custom struct, custom complex rule verification, order course acquisition and other methods).

  2. The statement rules

    rule1 := Salience 0 begin Print(flag-2) successObj := success(0) SuccessObj.AddDataParam("name0","test 000 value") return successObj end rule "case1" "CasE1 test case" Salience 1 // Begin a = 8 if a  1 { println("a  1") } else if a = 1  a 6 { println("a = 1  a 6") } else if a = 6  a  7 { println("a = 6  a  7") } else if a = 7  a  10 { println("a =7  a  10") } else { println("a  10") } end rule Salience 2 begin if flag0 {Print(flag+3) stag.StopTag = true successObj := success(222) successObj.AddDataParam("name2","test value") return successObj } end `
    Copy the code

    The rules are declared in the figure above. Print and success are our external injection methods, which will be formulated in the next step.

    Rule indicates the start of a new rule. The first value is the rule name (key when the result is returned), the second value is the description, and the third value salience indicates the priority of the rule

    The higher the priority number, the higher the priority. (When using the AsGivenSortedName method, the priority effect within the rule is ignored.)

  3. Initialize the rule pool by injecting in-rule dependent methods

    apis := make(map[string]interface{})
    apis["success"] = success
    apis["Print"] = fmt.Println
    
    var poolMinLen int64 = 50
    var poolMaxLen int64 = 100
    pool, err := engine.NewGenginePool(poolMinLen, poolMaxLen, engine.SortModel, rule1, apis)
    
    iferr ! =nil {
     fmt.Println(err.Error())
     return
    }
    Copy the code

    The first parameter poolMinLen indicates the minimum initialization pool of 50

    The second parameter, poolMaxLen, indicates that the maximum initialization pool is 100

    The third parameter to set the execution mode (divided into sequential and concurrent execution, etc.), only call ExecuteSelectedRules and ExecuteSelectedRulesConcurrent effective (follow-up to do rule pattern choice)

    The fourth parameter is the rule we configured

    The fifth is the variable values, methods, and so on that we inject

  4. Call execution rule

    data := make(map[string]interface{})
    data["flag"] = 2
    
    stag := engine.Stag{StopTag: false}
    data["stag"] = stag // displays the token to be injected
    
    //_ = pool.removerules ([]string{"case1"}) // RemoveRules
    / * _ = pool. UpdatePooledRulesIncremental (` / / new rules "case66" rule "case66 test cases" salience 3 begin Print (" case66 ") return false end `)*/
    
    _, resp := pool.ExecuteSelectedRulesWithControlAndStopTag(data, true, stag, []string{"case1"."case66"."case2"."case0"})
    fmt.Println(resp)
    //output:
    / / 5
    //map[case2:{222 map[name2:test value]}]
    
    Copy the code

    The business caller variable is injected, StopTag is declared interruptible, and the selected rule is executed

3. Business system application

Hierarchy diagram

Service scenarios Invoke the rule access layer based on the service id (ID) and run the associated rules based on the running mode.

The access layer obtains specific rules based on service ids and collects exceptions and results of service execution

The bottom part of rule information management is responsible for the maintenance and sorting of rule information data

Service access module division process

I. Process steps of business request side:

  1. The business side requests the execution rule (parameter is business number + business data)
  2. Rule execution Obtains the rule list corresponding to the service number and executes the rules based on the running mode (sequential or parallel) of the service
  3. After the execution is complete, the system returns the execution result for service use

Ii. Rule Management Capabilities:

  1. Input, modify and delete rules
  2. Rule merging Creates a service rule package and generates service numbers for service use
  3. Operating mode/specification input and output

4. To summarize

With the rapid development of the business, the life cycle of the code is getting shorter and shorter, and the project slowly develops into a terrible "monster", which eats up the patience of the r D students and is difficult to break the game despite repeated complaints. So much has been said above, how can we judge whether it is suitable to introduce rules engine?

First of all, consensus should be reached. Leaders and colleagues of production and research should agree that the current situation is worth doing, which can solve the pain points we have found at present (pain points can be found by finding out if else multi-branch decision-making scenarios in the simplest way, and judging according to historical changes and business needs).

At best, of course, you have a good sense of the business your code is serving.

The resources

www.bstek.com/#videos

Rencalo770. Making. IO/gengine_doc...

Github.com/bilibili/ge...

Search
About
mo4tech.com (Moment For Technology) is a global community with thousands techies from across the global hang out!Passionate technologists, be it gadget freaks, tech enthusiasts, coders, technopreneurs, or CIOs, you would find them all here.