← 返回首页
文章已发布29 次阅读admin2026年10月31日12 分钟阅读架构

风控域(risk)五层架构落地

一篇关于分层的立场评述:五层架构的价值不在整齐,而在于让风险判定的每个部件都可替换——规则能运营而不用发版。

附件

  • fig-risk-judge-flow.png(122 KB)下载

风控域(risk)五层架构落地

「不以规矩,不能成方圆。」规矩所以为规矩,因为它敢于在这一票说「不予批准」。本篇复盘 risk 域从零落地:风险规则、黑白名单、风险事件、风险评分一体化判定,五层齐备,集成测试 11 个全部通过。

一、界定:分层的意义是「让某物可替换」

六边形架构最常被读歪成一种目录仪式——api 放契约、domain 放实体、infrastructure 放 SQL,看起来工整,其实什么也没保证。分层的真正承诺只有一个:让某物可替换。判定引擎只依赖领域抽象,那么「规则怎么存、名单放哪里、事件怎么流」全都是可换的零件,而不是焊死在底座上的结构钢筋。

层交付物职责
api风险判定门面 + command/result跨域 Dubbo 契约,POJO 实现 Serializable
domainRiskRule / RiskEvent / RiskBlacklist / RiskWhitelist纯领域模型与仓储接口,零框架依赖
application规则管理 / 风险事件查询 / 风险判定用例编排与功能权限校验统一入口
infrastructureREST 控制器、MyBatis-Plus 仓储、Liquibase schema、判定引擎技术实现与持久化
bootstrap微服务启动编排独立部署形态

二、为什么必须:风控的两条命门矛盾

风控域与生俱来两个别处少见的矛盾。其一,风险规则要能在运营态改变——凌晨三点把误杀账户加回白名单,不能靠发版解决;其二,名单与规则绝不能一起失效——名单错了要能摁住规则,规则错了要能被名单逃过,二者的错误从来不商量着一起发生。

第一个矛盾要求规则与名单成为可运营的数据而不只是常量;第二个矛盾要求它们在判定时序上存在短路关系。两个答案汇成同一个结构:用例编排归 application,判定自洽归 domain,可变的存储归 infrastructure——语义变化才发版,名单运营不发版。

三、机理:宪法先于法律

判定时序是对这套结构最贴切的注脚:

judge(subject, action):
    1. 装载启用规则与名单
    2. whitelist 命中        → allow(短路)
    3. blacklist 命中        → deny(短路,写 RiskEvent)
    4. 逐条评估 RiskRule     → 累计风险评分
    5. 评分越过阈值          → deny,否则 allow
    6. 全过程写 RiskEvent

黑白名单短路优先是全文最重要的地基:白名单命中直接放行,黑名单命中直接拒绝,任何一方都不进入规则评估——避免规则误杀。它背后的次序观是:名单是判定的宪法,规则是判定的法律;宪法一句顶法律万句,先把宪法说清楚,法律才有发言的资格。无论结论如何都写 RiskEvent,判定过程自身也可被事后审计。

api 契约与其他域保持同一消费模式(单体本地 bean / 微服务 Dubbo Reference),异常收敛到 domains/common/domain 的三层体系并由 GlobalExceptionHandler 统一序列化——新域不再发明规范,规范本来就在走廊尽头。

risk judge flow

四、思辨:分层崇拜也是税

不能唱满赞歌。分层本身是一笔持续支付的成本:每一次「看得见却够不着」的绕行、每一份为接口而接口的样板,都在交税。若一个业务只有一条判定规则和一份名单,五层齐备就是给草棚镶上大理石。

六边形架构是付得起这笔税的复杂业务的门票。risk 域值得:规则、名单、事件、评分的复杂度名实相副。但下一个域来的时候,先审复杂度、再定层数——结构服务于业务,而不是反客为主。五层是答案,不是信仰。

五、回到现实:五步接入清单

  1. domains/pom.xml 与聚合 bootstrap/pom.xml 按依赖顺序接入(domain → application → infrastructure → bootstrap);
  2. 本域 Liquibase master 按域路径 include,应用配置 spring.liquibase.change-log 指向本域文件;
  3. 跨域端口双向打通:对外暴露 api 层 Dubbo 门面,对内消费 tag/auth 走 api 门面(单体本地 bean / 微服务 profile ReferenceBean);
  4. 鉴权收口:动作级资源编码 api.<domain>.<entity>.<action> seed + 应用层统一校验入口;数据权限单独经 data_permission_policies 表达;
  5. 日志对齐 audit 约定:控制器 LogUtils.interfaceLog、服务 DomainLogger、管理端写操作 @AuditLog。

后续演进(命中统计报表、名单批量导入、与 workflow 联动的人工复核)都是在这块地基上添砖,而不是另起炉灶。