Operations 14 min read

How Real-Time Rule Engines Balance Supply and Demand in Large-Scale Logistics

This article explains how a real‑time rule engine and performance‑optimized architecture are used to detect supply‑demand imbalances, enforce mutually exclusive adjustment rules, and efficiently scale capacity management for a nationwide logistics platform.

Huolala Tech
Huolala Tech
Huolala Tech
How Real-Time Rule Engines Balance Supply and Demand in Large-Scale Logistics

Business Background

Capacity resources are a core element of the Huolala business. As order volume grows, supply‑demand imbalance appears in professional markets: some are scarce, others are saturated. To rebalance, data‑driven promotion strategies are needed, but manual BI reports and ad‑hoc queries cannot cover nationwide adjustments efficiently.

The big‑data team therefore built an online real‑time capacity‑adjustment system that combines metric factors with a rule engine to achieve supply‑demand equilibrium for drivers, users and the platform.

Project Architecture

The system is divided vertically into application layer, service layer, engine layer and data storage layer. This article focuses on the practice of strategy configuration in the application layer and the task‑calculation part in the engine layer, especially the rule engine and Kubernetes aspects.

Strategy Groups

Strategy Modes

Capacity balancing is divided into three strategies:

Diagnosis strategy: BI/algorithm engineers define diagnostic rules that select Origin‑Destination grids (OD) needing adjustment, then apply actions such as increasing or decreasing coupon quantities or driver/user subsidies.

Review strategy: Daily review tags OD grids after diagnosis to observe the effect; when review rules are satisfied, the process ends or continues with optimization.

Optimization strategy: Continuous refinement based on review results until the supply‑demand state converges.

Rules

Rules are the smallest atomic units for filtering OD. Each rule consists of a left value, a relational operator, and a right value. Example:

Left Value   Operator   Right Value
Variable     =, <=, >, <, ==, !=, is, contains...   Specific number/text

Example rule: “预付响应单量 >= 100”.

Rule Group

Complex OD selections may require combining multiple rules with logical operators AND/OR, e.g., “RuleA && (RuleB || RuleC)”.

Rule Mutual Exclusion Validation

The purpose is to ensure that rule groups do not produce overlapping OD sets, i.e., Rule A ∩ Rule B = ∅. Overlap would cause multiple adjustment packages to act on the same OD, leading to unpredictable errors.

Direct database intersection checks are unreliable, slow, and depend on changing source data. Instead, a mathematical approach based on Disjunctive Normal Form (DNF) is used.

Each rule group is represented as a tree:

First‑level nodes store logical OR.

Second‑level nodes store logical AND.

Leaf nodes store relational expressions.

For single‑rule groups, the same structure is used with a single leaf.

Mutual‑exclusion algorithm: two rule objects intersect only if every variable in both objects has a non‑empty intersection. If any pair of objects intersect, the rule group is not mutually exclusive.

Rule Engine Practice

BI/algorithm staff generate many strategies daily, each containing rules. Traditional if…else code requires code changes and redeployment for every rule change, which is inefficient and risky.

Using a rule engine replaces hard‑coded logic with dynamic scripts, allowing rules to be changed without redeployment.

Engine Comparison

Engine      Intro                                   Learning Cost   Performance                              Function
Drools      Open‑source BRMS, fast Rete matching    High            High (Rete)                              Rich
IKExpression Lightweight Java expression parser    Low             Low (interpreted)                         Limited
Aviator     High‑performance Java expression engine Low             High (compiled bytecode)                  Richer than IKExpression, less than Drools

Considering learning cost, performance, and functional fit, Aviator was selected for this project.

Implementation Steps

XXL‑Job scans configured OD strategies every 5 minutes, generates string‑format logical expressions, and stores them in MySQL.

When matching OD, the expression is loaded, compiled by Aviator, and cached.

OD metric values are passed as the environment to the compiled expression.

If the expression evaluates to true, the corresponding supply‑demand adjustment package is executed; otherwise, an alternative package runs.

String expression = "(a > 50 && b > 200) || c > 10";
Expression compiledExp = AviatorEvaluator.compile(md5Hash(md5Hash(expression)), expression, true);
// Query OD and set as newEnv arguments
Boolean matched = (Boolean) compiledExp.execute(compiledExp.newEnv("a", 300, "b", 450, "c", 700));
if (matched) {
    // supply‑demand strategy...
} else {
    // other adjustments...
}

Performance Optimization Practices

The OD adjustment pipeline consists of querying OD from the database, matching with the rule engine, and triggering the appropriate adjustment package. Optimizations focus on fast OD retrieval and efficient rule matching.

OD Query Optimization

Even with indexed queries, large batch sizes cause timeouts. A “batch merge‑split” technique is introduced: small batches are merged, large batches are split into sub‑batches, and Kubernetes launches multiple Jobs with parallel tasks.

Rule Matching Optimization

Cache hot OD using an LRU cache; reuse previous match results instead of re‑evaluating with Aviator.

Enable Aviator’s runtime optimization mode.

Cache compiled expressions; use a double‑MD5 hash as the cache key to avoid collisions.

Pass external variables via Expression#newEnv(..) to enable symbolization and reduce variable access overhead.

String expressionKey = md5Hash(md5Hash(expression));
OdMatchStatus odMatchStatus = lruCacheMap.get(expressionKey);
if (odMatchStatus != null) {
    // hit cache, skip evaluation
} else {
    // evaluate with Aviator and possibly add to cache
}
AviatorEvaluator.getInstance()
    .setOption(Options.OPTIMIZE_LEVEL, AviatorEvaluator.EVAL);
Expression compiledExp = AviatorEvaluator.compile(md5Hash(md5Hash(expression)), expression, true);

Conclusion

This article introduced the principle of rule mutual‑exclusion validation, its application in capacity‑adjustment scenarios, and practical performance optimizations. Capacity adjustment is a large‑scale engineering problem; future articles will explore additional aspects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

rule engineKubernetesAviatorcapacity balancing
Huolala Tech
Written by

Huolala Tech

Technology reshapes logistics

0 followers
Reader feedback

How this landed with the community

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.