在电商营销活动中,复杂的优惠券、满减、阶梯折扣规则往往让开发团队头疼不已。每次调整规则都需要修改代码、提需求、打补丁、重新上线,既耗时又容易出错。更严重的是,如果促销策略设计不当,可能带来巨大的财务损失。
传统投放、风控、内容推荐系统常常面临两个核心难题:
- 规则配置复杂、上线慢、研发效率低
- 策略迭代需要灰度验证,但难以做到可观测、可降级、安全可控
本文将带你从零实现一个开箱可用的「规则引擎 + 灰度发布系统」,采用:
- Golang + Kafka + Redis
- CEL 作为规则表达式
- Edge 侧规则执行器(本地缓存 + Token Bucket 限流)
- Publisher 规则发布器(含灰度下发)
- Webhook 动作执行器(业务回调)
- 一键 docker-compose 启动全系统
不仅讲解原理,还提供完整可运行源码结构,是你构建实际生产级策略平台的最佳指南。
一、为什么需要"规则引擎 + 灰度发布"?
在营销投放、推荐系统、内容分发、风控系统等真实业务中,我们常常需要根据用户画像及行为或事件执行相应的规则,例如:
- A/B 实验
- 新广告投放规则
- 用户优惠券兜底逻辑
- 风控拦截逻辑
但传统方式存在几个痛点:
| 痛点 |
描述 |
| 规则逻辑硬编码 |
每次改规则都需要发版,贻误战机 |
| 发布流程慢 |
回归测试、上线、验证时间长 |
| 无法灰度验证 |
直接上线,风险巨大 |
| 下发方式不统一 |
分布式节点同步困难 |
| 可观测性弱 |
无法知道规则执行情况 |
为解决这些问题,一个现代策略平台应当具备:
- 规则可视化管理
- 可编译、可校验的统一规则 DSL(如 CEL)
- Kafka 规则实时下发
- 支持灰度、全量、回滚
- Edge 侧本地缓存,支持降级
- 限流与隔离(token bucket)
- Webhook 动作执行(通知、投放、补偿逻辑等)
系统架构如下:
┌──────────────┐ ┌─────────────┐
│ Dashboard │ POST │ Publisher │
│(规则配置中心)│ ───▶ │(灰度规则下发)│
└──────────────┘ └───────┬─────┘
│ Kafka
▼
┌────────────┐
│ Edge │
│(规则执行器)│───▶ Webhook Server
└────────────┘
▲ Redis
│(规则缓存 + 限流)
二、核心能力拆解
① 规则编译:CEL 表达式
CEL 是 Google 开源的表达式语言,语法简单、安全可控、性能极高(比 Lua 快 5~20 倍),是构建规则引擎的理想选择。
示例规则:给注册 30 天内、0 下单、风控评分 < 0.3 的新用户发一张 20 元优惠券,并仅灰度 10% 进行测试。
{
"id":"rule_notify",
"version":"v1",
"enabled":true,
"condition":"user[\"register_days\"] < 30 && user[\"order_count\"] == 0 && ml[\"score\"] < 0.3",
"action":{"type":"call_webhook","params":{"url":"http://webhook-server:9090/coupon"}},
"strategy":{"type":"percentage","percentage":10},
"limit_per_second": 100
}
Edge 侧使用 CEL 编译:
env, _ := cel.NewEnv(
cel.Variable("user", cel.MapType(cel.StringType, cel.DynType)),
)
ast, _ := env.Compile(rule.Filter)
prog, _ := env.Program(ast)
out, _, _ := prog.Eval(map[string]interface{}{
"user": userInfo,
})
② 灰度发布机制
Publisher 会按如下方式下发规则:
- 100% → 全量规则下发
- 10% → 使用一致性 hash 做流量控制(例如按 userId)
- 支持 rollback
Publisher 发布营销策略后,所有 Edge 节点 5 秒内收到策略更新并生效。
msg := RuleMessage{
RuleID: "rule_notify",
Expr: `user.register_days < 30 &&
user.order_count == 0 &&
ml.score < 0.3 &&
(region == "CN" || region == "HK")`,
GrayPercent: 10,
LimitPerSec: 100,
ActionURL: "http://webhook-server:9090/coupon",
}
value, _ := json.Marshal(msg)
writer.WriteMessages(ctx, kafka.Message{Value: value})
Kafka 是天然的规则广播管道,提供了高吞吐量和可靠性。当然在实际开发中,可以根据需求及自身资源选择适合的消息中间件。
③ Edge 本地规则执行器
当用户打开 App → 请求 Edge 时的执行逻辑为:
// 1. 灰度命中?
if !HitGray(rule.GrayPercent, user.ID) {
return "SKIPPED_GRAY"
}
// 2. 规则表达式满足?
matched, err := rule.Program.Eval(vars)
if err != nil || !matched {
return "SKIPPED_EXPR"
}
// 3. 限流检查(Redis Token Bucket)
if !TokenBucketAllow(rule.RuleID, rule.LimitPerSec) {
return "LIMITED"
}
// 4. 执行动作(Webhook)
CallWebhook(rule.ActionURL, vars)
return "MATCHED"
注意第三步:在营销投放中限流非常关键,因为不限流可能导致突发高流量压垮优惠券系统,造成严重事故。Token-Bucket 算法允许合理的流量突刺,更适合营销业务场景。
④ Webhook 动作执行器
Webhook Server 是业务处理端,负责:
- 接收 action 回调
- 执行营销、投放、风控等实际业务逻辑
- 记录执行日志
命中规则后 Edge 会调用:
http.Post(rule.ActionURL, "application/json", bytes.NewBuffer(body))
用于:
- 发送优惠券
- 触发 Push
- 营销投放
- 消息通知
- 落地风控动作
Webhook 服务可按业务需求灵活扩展。
⑤ Dashboard 可视化报表
由于实际因素限制,本文未详细实现 Dashboard 模块。但在实际营销活动中,运营数据的可视化展示至关重要。通过合理的前端框架和数据处理,可以避免开发人员手动拉取数据的低效工作。
// 发送POST请求到边缘节点进行规则评估
resp, err := client.Post(edge+"/eval/rule_notify", "application/json", bytes.NewReader(b))
status := "ERROR"
if err == nil {
// 读取响应体
body, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
// 解析响应JSON
var er map[string]interface{}
_ = json.Unmarshal(body, &er)
// 根据响应结果确定状态
if m, ok := er["matched"].(bool); ok && m {
if e, ok2 := er["error"].(string); ok2 && e != "" {
status = "LIMITED"
} else {
status = "MATCHED"
}
} else {
// 更详细地处理未匹配的情况
if e, ok := er["error"].(string); ok && e == "rule not found" {
status = "NO_RULE"
} else {
status = "SKIPPED"
}
}
}
整个架构的优势:
- 策略人员可立即发布规则
- Edge 侧无感更新
- Kafka 保证多节点一致性
- Redis 限流保障系统安全
- 灰度 10% 防止全量事故
- Webhook 解耦营销动作
三、Go 语言实现优势
选择 Go 语言实现该系统具有明显优势:
- 高性能并发处理,适合高并发营销场景
- 编译为单一二进制文件,部署简单
- 丰富的标准库和生态系统
- 出色的内存管理和垃圾回收机制
这个完整的营销投放系统具备生产级质量,开发者可以根据实际需求进行适当修改后直接使用。
源码下载
👉 GitHub:
https://github.com/louis-xie-programmer/rule-engine-gray
👉 Gitee:
https://gitee.com/louis_xie/rule-engine-gray