找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3518

积分

0

好友

468

主题
发表于 2 小时前 | 查看: 2| 回复: 0

在云栈社区,经常听到开发者吐槽:运营天天要求改规则,每次都得走一遍完整的发布流程,耗时耗力。今天介绍的 开源规则引擎 RuleEngine 正是要解决这个痛点——它把业务规则的变更从代码中剥离出来,交给运营或产品自助完成,Web 配置完直接生效,业务系统无需重启。

规则引擎演进:从硬编码到可视化编排

反向定位:把规则改动从代码里剥出来

风控、营销、定价、优惠这些业务规则的共性是:变得快、变得乱、变得不讲道理。运营今天说「白名单加 3 个手机号」、明天说「下单金额 > 500 才发优惠券」、后天又说「IP 黑名单临时屏蔽 50 个段」。如果这些规则全写在代码里:

  • 改一条 → 改 Java 代码 → CR → CI → 灰度 → 全量 → 半天到一天没了
  • 紧急变更等不及发版,运营拿 SQL 直连库改 → 没审计、没回滚
  • 月底复盘时谁也说不清楚「这条规则当时为什么开」。

这里推荐的 RuleEngine 是一个开源 Java 规则引擎,它不是「让你写更优雅的 if-else」,而是「把『改规则』这件事从代码里剥出来交给运营/PM 自助」

  • Web 界面配规则:运营自己拖拽组合「条件 + 阈值 + 动作」,不需要工程师;
  • HTTP 接口执行:Java 服务调一下 /ruleEngine/generalRule/execute,传业务参数,回来就是判定结果;
  • 零发版生效:Web 上保存即生效,无需重启业务服务

核心理念:业务规则的变化频率,远高于代码本身的变化频率——把它们解耦开,是工程纪律。

横向对比:4 个规则引擎方案怎么选

不是所有项目都该上规则引擎。先看自己在哪个象限:

方案 形态 配置难度 改完是否要发版 致命短板
硬编码 if-else 代码 0 每次都要发版 改一条要走完整 CI/CD
Drools Java 库 改 DRL 文件、要部署 DSL 学习曲线陡,运营写不来
Groovy / QLExpress 脚本 嵌入式 字符串热更新可省发版 仍是写代码,运营碰不了
本文方案:Web 规则引擎 独立服务 (拖拽) 零发版 多一个服务依赖

判断很简单

  • 规则数量 < 5 条、几乎不变:硬编码就好,别上重武器;
  • 规则在工程师内部维护:Groovy / QLExpress 脚本是最轻的活路,能热更新;
  • 规则要交给运营 / PM 自己改、变更频繁:Web 规则引擎是唯一答案
  • 真复杂的工业级规则(保险定价、信贷决策):Drools仍有它的位置。

3 个真实业务场景

场景 1:风控黑白名单

规则:当 phone IN 黑名单库 OR ip IN 屏蔽段 → 拒绝下单

痛点:黑名单每天都在变,每次都改代码不现实。用法:运营在 Web 配「条件 + 黑名单数据源」,下单接口执行规则前调一次:

PhoneBlockRule input = new PhoneBlockRule();
input.setPhone(req.getPhone());
input.setIp(req.getClientIp());
Output result = ruleEngineClient.generalRule().execute(input);
if (result.isHit()) throw new BlockedException("命中风控");

收益:黑名单变更秒级生效,运营自助操作,开发者解放。

场景 2:优惠券发放规则

规则:用户是新客 AND 下单金额 > 500 AND 城市 IN [北京/上海/深圳] → 发 50 元券

痛点:大促规则一天一变,全靠开发改 if-else 极其折磨。用法:每个促销活动配成一条规则,结束直接禁用——库存、券发放走原系统接口,规则引擎只负责「判定是否发」。收益:促销上线时间从 3 天压到 1 小时。

场景 3:参数动态校验

规则:手机号长度 = 11 AND 前缀 IN [13/14/15/16/17/18/19] AND 不在内部测试号段

痛点:测试号段、临时灰度号段经常变,校验代码改起来繁琐。收益:校验逻辑放规则引擎,业务代码就保留「调一次规则引擎」一行。

接入 3 步:装服务 + 装客户端 + 调规则

第 1 步:装规则引擎服务

SpringBoot 2.2.11 + RabbitMQ + Redis + MySQL 5.7+ + MyBatis-Plus

部署后访问 Web 控制台 http://ruleengine.cn,配规则。其中用到了 Spring Boot 作为基础框架,结合 Redis 存储缓存。

第 2 步:业务系统接客户端

<dependency>
  <groupId>cn.ruleengine</groupId>
  <artifactId>rule-engine-client</artifactId>
  <version>2.0</version>
</dependency>

application.yml

rule:
  engine:
    baseUrl: http://ruleserver.cn
    workspaceCode: default
    accessKeyId: root
    accessKeySecret: 123456
    feignConfig:      # 可选
      request:
        connectTimeoutMillis: 3000
        readTimeoutMillis: 3500
      retryer:
        period: 2000
        maxPeriod: 2000
        maxAttempts: 3

关键点:超时时间 + 重试次数要根据业务调——规则引擎挂了不能让业务接口跟着雪崩

第 3 步:业务代码调规则

@EnableRuleEngine
@SpringBootTest
public class RuleTest {

    @Resource
    private RuleEngineClient ruleEngineClient;

    @Test
    public void testPhoneRule() {
        PhoneTestRule input = new PhoneTestRule();
        input.setPhone("13400000000");

        GeneralRule rule = ruleEngineClient.generalRule();
        Output output = rule.execute(input);
        System.out.println(output);
    }
}

@Data
@Model(code = "phoneRuletest")
public class PhoneTestRule {
    @InputParameter(code = "phone")
    private String phone;
}

注意@Model(code = "phoneRuletest") 必须和 Web 上配置的规则 code 完全对齐,错一个字母规则就调不到。

也可以走 HTTP 不用客户端(适合非 Java 项目):

POST http://ruleserver.cn/ruleEngine/generalRule/execute
Content-Type: application/json

{
  "code": "phoneRuletest",
  "workspaceCode": "default",
  "accessKeyId": "略",
  "accessKeySecret": "略",
  "param": { "phone": "13400000000" }
}

自定义 HTTP 客户端(用 RestTemplate 替代默认 Feign):

@Component
@Import({RestTemplate.class})
public class RuleEngineClientConfig {

    @Resource
    private RestTemplate restTemplate;

    @Bean
    public GeneralRuleInterface generalRuleInterface() {
        return new GeneralRuleInterface() {
            @Override
            public ExecuteResult execute(ExecuteParam param) {
                return restTemplate.postForObject(
                    "http://ruleserver.cn/ruleEngine/generalRule/execute",
                    param, ExecuteResult.class);
            }
            @Override
            public IsExistsResult isExists(IsExistsParam p) { return null; }
            @Override
            public BatchExecuteResult batchExecute(BatchParam p) { return null; }
        };
    }
}

可视化配置面板

实际操作界面长这样——条件、阈值、动作都拖拽配置:

规则引擎后台分析页

规则引擎工作空间列表

规则引擎内置函数列表

规则引擎决策表管理

最直接的好处:运营 / PM 不需要懂 Java 也能配。把这种 UI 截图发给业务方,他们看一眼就懂——比让他们读 if-else 代码门槛低 100 倍。

4 个真实使用边界

边界 1:规则引擎挂了不能让业务接口跟着挂(最常见)
业务接口里调规则引擎的接口,必须设超时 + 兜底策略:超时不返回时走默认放行 / 默认拒绝(按业务决定)。没兜底就是把所有业务接口的 SLA 绑给了规则引擎——这是规则引擎的头号坑。

边界 2:高频规则要加缓存(常见)
每次下单都调,QPS 一上去引擎被打满。修法:客户端对「规则版本号 + 入参」做短期缓存(30 秒~5 分钟),版本变更失效;或把规则推到 Redis 让业务侧本地匹配,引擎只管编译。

边界 3:规则变更要审计 + 灰度(少见但破坏力大)
「运营改规则秒生效」是优点也是风险——运营手抖把白名单全清了,业务直接挂。必须配:① 规则变更审计日志;② 重大规则变更要双人审批;③ 改完先灰度 10% 流量观察 5 分钟再全量。生产规则引擎和数据库是同一个量级的关键基础设施

边界 4:复杂规则别硬塞(高级场景)
规则引擎适合「条件组合判定 + 阈值比较」这类清晰逻辑——不要硬塞循环、递归、复杂数学计算。复杂的算 score(用户行为) > threshold 应该走专门的算法服务,规则引擎只调用算法服务的输出做最终判定。

最后聊两句

规则引擎不是「把代码搬到 Web 上」——它是把「规则的变更频率」和「代码的变更频率」解耦好的工程结构不是没有变化,是让易变的部分不影响稳定的部分

仓库:gitee.com/aizuda/rule-engine-front-open

规则引擎设计原则总结




上一篇:腾讯混元:仅靠堆任务不行!Skill Graphs用技能图谱实现Agent训练多样性飞跃
下一篇:你越是这样,领导越不敢动你:20年职场老鸟的深度感悟
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-5-3 23:29 , Processed in 0.834619 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表