摘要:本文介绍一套面向海外支付场景的计费中台架构实践,通过领域驱动设计(DDD)和配置化引擎,实现新业务接入成本降低 80%、代码复用率提升 70%、计费成功率 100% 的工程目标。
关键词:计费中台;领域驱动设计;配置化引擎;架构实践
1. 背景与问题
1.1 业务挑战
海外支付业务面临地域多样性、渠道复杂性、业务多元性、场景灵活性等挑战,各国监管政策、费率结构差异显著,计费逻辑需快速适配迭代。
1.2 架构痛点
传统计费架构采用分散式嵌入式设计,计费能力散落在路由系统(router)、网关系统(gateway)等多个子系统中:
核心问题:
- 代码重复:相同计费逻辑多系统重复实现,复用率低于 30%
- 一致性风险:路由估算与网关实际扣费存在偏差,对账困难
- 变更成本高:新增渠道需多系统协同发布,周期 2-3 周
- 追溯困难:计费日志分散,全链路定位问题成本高
1.3 解决思路
构建独立计费中台(billing) ,将计费能力从业务系统中剥离,统一收归至独立中台,实现能力复用、配置驱动、热更新。
2. 架构方案
2.1 架构演进
【改造前】 【改造后】
分散计费模式 统一计费架构
· 逻辑散落 → · 能力下沉
· 硬编码为主 · 配置驱动
· 需重启生效 · 热更新
2.2 统一计费架构
2.3 分层设计
| 层级 | 职责 | 关键技术 |
|---|---|---|
| 业务接入层 | 调用计费服务 | router、gateway |
| 网关层 | 流量控制、安全防护 | Kong / Nginx |
| 计费服务层 | RESTful API | Spring Cloud |
| 核心引擎层 | 规则解析、算法执行 | Aviator |
| 缓存层 | 配置数据缓存 | Redis Cluster |
| 数据持久层 | 配置与日志存储 | MySQL |
3. 领域建模
3.1 核心实体
基于 DDD 思想,对计费领域进行抽象建模:
3.2 实体定义
| 实体 | 核心属性 | 行为 |
|---|---|---|
| 租户 | 租户 ID、业务线、状态 | 获取计费配置、权限校验 |
| 计费场景 | 场景编码、上下文参数 | 规则匹配、参数验证 |
| 计费规则 | 规则 ID、优先级、条件、公式 | 条件评估、执行计算 |
| 费率配置 | 费率值、计费模式 | 费用计算 |
| 计费结果 | 流水号、金额、明细 | 结果聚合、明细展开 |
4. 核心设计
4.1 事件风暴
通过事件风暴识别计费领域核心业务事件:
4.2 聚合根设计
采用聚合根模式封装计费规则,确保业务一致性边界:
public class BillingRuleAggregate {
private RuleId ruleId;
private ConditionSpec condition;
private FormulaSpec formula;
private RateConfig rateConfig;
public boolean matches(BillingContext context) {
return condition.evaluate(context);
}
public BillingResult calculate(BillingContext context) {
Decimal amount = formula.compute(context, rateConfig);
return BillingResult.create(amount, getCalculationDetails());
}
}
4.3 配置化体系
支持多维度配置组合,实现"配置即开发":
采用 Aviator 作为表达式求值引擎,支持条件表达式、公式表达式、三元表达式、函数调用等:
| 表达式类型 | 语法示例 | 应用场景 |
|---|---|---|
| 条件表达式 | amount >= 1000 && channel == 'BANK_A' | 规则匹配 |
| 公式表达式 | amount * rate | 比例费用计算 |
| 三元表达式 | amount > 10000 ? 0.008 : 0.01 | 条件费率 |
| 函数调用 | max(baseFee, amount * rate) | 保底费用 |
4.4 算法模型
计费引擎支持固定费用和比例费用两种模式:
5. 关键实现
5.1 配置缓存架构
采用多级缓存 + 变更推送架构保障高性能:
- 多级缓存:Caffeine 本地缓存 + Redis 分布式缓存
- 变更推送:Redis Pub/Sub 实时通知各节点
- 缓存预热:服务启动时预加载全量配置
- 降级策略:缓存失效时降级至数据库
5.2 规则执行引擎
基于 Aviator 实现动态规则解析:
private static final Map<String, Expression> EXPRESSION_CACHE = new ConcurrentHashMap<>();
public Expression getExpression(String expressionStr) {
return EXPRESSION_CACHE.computeIfAbsent(expressionStr, AviatorEvaluator::compile);
}
工作流程:表达式解析 → 字节码编译 → 缓存复用 → 环境注入 → 结果返回
5.3 结构化日志
日志支持全链路追溯与审计:
{
"traceId": "计费链路追踪 ID",
"tenantId": "租户标识",
"scenarioCode": "场景编码",
"matchedRules": [{"ruleId": "规则 ID", "ruleName": "规则名称"}],
"calculation": {"originalAmount": "原始金额", "rateApplied": "应用费率", "finalFee": "最终费用"},
"result": {"status": "计费状态", "feeAmount": "费用金额"}
}
6. 系统成效
6.1 核心指标
| 指标 | 改进幅度 |
|---|---|
| 新业务接入成本 | 降低 80% |
| 综合运营成本 | 下降 25% |
| 代码复用率 | 提升 70% |
| 计费成功率 | 100% |
| 变更效率 | 提升 100 倍 |
当前系统支撑近 20 家交易渠道、10 余条业务线、近 10 种交易场景的计费需求。
6.2 性能表现
| 指标 | 数值 |
|---|---|
| 配置读取延迟 | < 1ms |
| 响应时间 | 降低 40% |
| 吞吐量 | 提升 5 倍 |
| 资源利用率 | 提升 60% |
6.3 稳定性表现
| 能力 | 说明 |
|---|---|
| 故障隔离 | 独立部署、熔断降级 |
| 灰度发布 | 配置版本化、分批推送 |
| 监控告警 | 5 分钟内发现故障 |
7. 架构扩展能力
7.1 清结算场景
计费引擎的算费能力可扩展至清结算领域,支撑商户结算、分润、服务费等场景:
7.2 插件化扩展
系统采用插件化架构,支持按需扩展新的计费场景:
| 扩展场景 | 说明 |
|---|---|
| 内部计费 | 内部系统间调用计费 |
| 营销活动计费 | 优惠券、折扣等营销活动 |
| 风控计费 | 风控服务调用计费 |
| API 调用计费 | 开放平台 API 调用计费 |
8. 总结
核心经验
- 领域抽象:深入理解业务,提炼通用模型
- 配置驱动:变化部分配置化,提升灵活性
- 缓存保障:多级缓存策略保障高性能
- 日志基石:结构化日志支持全链路追溯
设计原则
| 原则 | 说明 |
|---|---|
| 高内聚低耦合 | 计费能力内聚于中台,与业务系统解耦 |
| 配置与代码分离 | 计费规则配置化,无需修改代码 |
| 水平扩展 | 无状态设计,支持弹性扩缩容 |
| 可观测性 | 完整的日志、指标、追踪能力 |