Backend Development 10 min read

Understanding Rule Engines and Their Application in ZuanZuan Wallet with EasyRules Performance Analysis

This article explains the concepts of rule engines versus imperative programming, demonstrates rule‑engine implementation with EasyRules through code examples, discusses its business value and application in ZuanZuan Wallet, and analyzes the performance of EasyRules in rule evaluation and execution.

Zhuanzhuan Tech
Zhuanzhuan Tech
Zhuanzhuan Tech
Understanding Rule Engines and Their Application in ZuanZuan Wallet with EasyRules Performance Analysis

1. What Is a Rule Engine and Imperative Programming

To illustrate the difference, a simple number‑guessing game is first presented using an imperative style with a // generate a random integer secret = random(1, 100) // initialize guess count guesses = 0 while true do guess = input("Guess a number between 1 and 100: ") guesses = guesses + 1 if guess < secret then print("Too low, try again.") else if guess > secret then print("Too high, try again.") else print("you guessed it in", guesses, "guesses!") break end if end while loop, highlighting the explicit control flow of imperative programming.

In contrast, the same logic is expressed with a rule‑engine style using EasyRules syntax:

// rule 1
rule "Guess a number"
when
  $guess: Integer()
  $secret: Integer(intValue > $guess)
then
  System.out.println("Too low, try again.");
end
// rule 2
rule "Guess a number"
when
  $guess: Integer()
  $secret: Integer(intValue < $guess)
then
  System.out.println("Too high, try again.");
end
// rule 3
rule "Guess a number"
when
  $guess: Integer()
  $secret: Integer(intValue == $guess)
then
  System.out.println("you guessed it!");
end

The rule‑engine approach abstracts business logic into declarative rules, making it easier for non‑technical users to modify behavior without changing code.

Value of Rule Engine Programming

By externalizing business logic into rules, organizations gain high extensibility and maintainability; business analysts can adjust conditions and actions without redeploying the application, reducing coupling between business and technical layers.

2. Application of Rule Engine in ZuanZuan Wallet

ZuanZuan Wallet offers interest‑free installment shopping, small‑loan services, and one‑yuan phone rentals. The product team needed to display different cards (installment, loan, rental) based on a user’s current business state.

Using a traditional imperative approach would require many nested if‑else statements, making the code hard to maintain and requiring a new release for any rule change.

Instead, a rule engine was adopted. Key steps include:

Rule Modeling: Identify common conditions such as account disabled, new user, loan eligibility, and credit limit, then ensure the rule set covers all possible states.

Engine Component Selection: Evaluate existing engines (Drools, EasyRules, Aviator, LiteFlow) and choose EasyRules for its lightweight nature.

Overall Design: Store rule configurations in Apollo for dynamic updates, feed user facts into the engine, and compute the resulting card states.

3. EasyRules Performance Analysis

The performance of EasyRules is examined by reviewing its core source code.

Rule Evaluation

void doFire(Rules rules, Facts facts) {
    for (Rule rule : rules) { // iterate over rules
        boolean evaluationResult = false;
        evaluationResult = rule.evaluate(facts); // evaluate condition
        if (evaluationResult) {
            rule.execute(facts); // execute action if true
        }
    }
}

This loop evaluates each rule sequentially; for large rule sets, a Rete algorithm could be more efficient.

Rule Execution

protected Rule createSimpleRule(RuleDefinition ruleDefinition) {
    MVELRule mvelRule = new MVELRule(parserContext)
        .name(ruleDefinition.getName())
        .priority(ruleDefinition.getPriority())
        .when(ruleDefinition.getCondition()); // step 1
    for (String action : ruleDefinition.getActions()) {
        mvelRule.then(action); // step 2
    }
    return mvelRule;
}

public MVELAction MVELAction(String expression, ParserContext parserContext) {
    this.expression = expression;
    compiledExpression = MVEL.compileExpression(expression, parserContext); // compile expression
}

EasyRules compiles MVEL/SpEL expressions ahead of time, resulting in low execution latency. In a 618 promotion stress test, the engine handled a peak QPS of 15,000 with a maximum response time of only 10.3 ms.

Performance Results

Author: Li Wen, ZuanZuan Financial Technology R&D Engineer

For more business practice insights from ZuanZuan, follow the official WeChat public account.

javaperformance analysisbusiness rulesEasy Rules
Zhuanzhuan Tech
Written by

Zhuanzhuan Tech

A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.