开发规范
设计业务组件的理由和经验杂谈
- 开闭原则:将业务中心内部
复杂易变
的业务逻辑从业务功能中剥离出来,这是内部的修改,不应该影响前台应用的正常运行。应当遵循对扩展开放,对修改封闭
的开闭原则。 - 性能原则:在端到端的业务流程中,引入业务组件,须避免增加大量额外的
网络IO开销
,影响最终的用户体验。 - 领域事件:规则引擎内嵌到事件源/业务领域中心,这样可以最快的途径、最便捷的方式
接收领域事件/业务对象/事实数据
。 - 高内聚松耦合:业务中心的业务逻辑,本质上是业务中心的不可或缺的一部分,应当
高内聚
在同一个服务之中。否则,不论前期的需求沟通、设计、开发,到后期的故障排查,都将成为一个噩梦,会浪费大量的人力资源(沟通成本/协作成本)。因此,业务中心的业务逻辑应该尽量保持高内聚松耦合,无需对外过多暴露,以便于业务中心的快速迭代和响应。 - 面向切面:业务规则本来就是业务系统的一部分,业务接口实现代码的一部分,
通过AOP的方式,将其切出来/拆出来,但在运行时要装回去/缝合上
。 - 边缘计算:
让算法(规则)靠近数据(事件)
,而不是让是事件靠近规则。因为事件源会源源不断产生新的事件,这无疑会浪费大量的网络IO流量和存储成本,影响最终用户的体验。让规则文件和引擎尽量靠近事件源,而不是远离事件源(业务中心)。 - 关注点分离:声明式逻辑和命令式功能在
物理或逻辑
静态层面的分离,但不是系统或网络
运行层面的分离。 - 请求链路:渠道应用 -> 业务场景 -> 触发点 -> 能力开放运营平台/跨中心融合服务平台 -> 业务中心的API(接口实现包含业务逻辑和业务功能)-> 取数插件(可选) -> 业务规则组件(
业务逻辑涉及业务规则和业务对象
) -> 规则文件 -> 左手部分/条件/谓词 -> 右手部分/动作/算子 -> 决策结果。 - 避免单点故障:业务规则组件内嵌的方式运行,实际上是将规则引擎服务以分布式方式部署,以提高业务的容量和可用性。避免规则中心的单点故障,造成业务中心的群体故障。
绝不能要让规则中心,成为故障中心
。 - 可打包的业务能力:业务规则组件封装了
业务逻辑决策的能力
,包含业务规则的编写、事实数据结构的定义、规则引擎等功能。将其作为一个标准化组件内嵌到事件源
,原则上就不需要取数引擎
这个东西了,最多搞一个定制的取数插件
。 - 值的不变性:事实数据最好具有
不变性
(Java的Record和Lambda),这样并发多线程就简单了。 - 嵌入式部署:规则很轻,数据很重,所以内嵌的方式更为合适。至少可以做到
Sidecar
模式。 - 独立式部署:当调用方可以提供完整的事实数据时,可以独立部署。规则文件和事实结构,可事先配置好。因为事实数据及其推论是在某个时间段,可能具有不变性,而为了提高响应速度,
是否要考虑对执行结果做缓存
? - 接口映射数据模型:业务域、渠道应用、业务场景、业务规则、业务对象,某个接口中操作了哪些数据库表。
- 复杂易变: 业务规则组件适合
复杂易变
业务逻辑的场景。如果场景的业务规则不复杂(比如if的层次只有1层,没有嵌套;且if的代码量少于一个屏幕的行数),不一定要提取到规则文件;如果场景的业务规则不是多变的,也就是长时间不变的,引入规则引擎的好处可能也并不明显。 - 不影响业务中心的推广:当业务中心内嵌集成了业务规则组件,只要关闭掉向统一规则中心的汇聚信息的开关,就
不影响其在省外的推广
,因为业务规则组件可以独立于规则中心运行
。 升级工作相互不影响
:统一规则中心升级时,不影响业务中心的业务,也不需要业务中心配合;反之亦然,业务中心的升级不需要规则中心配合。业务规则组件升级时,可仅针对业务中心逐个升级。不能牵一发而动全身,一方升级,多方受影响
。- 集中式管理:
业务规则中心做什么,不做什么
?不负责引擎执行,不负责存储事实数据,只收集规则信息、事实结构信息以及规则的运行日志,进行多维度的集中式管理(运营看板)。事实结构信息的展示、规则文件信息的展示(DMN/BPMN/PMML)、规则引擎运行日志信息的存储。日志考虑使用TDengine存储,子表,一个规则文件,每执行一次,产生一条执行日志,超级别表就有业务域、业务触点/渠道/应用、业务场景/接口、业务规则等标签。 - 分布式运行:
业务规则组件做什么,不做什么
? 提供统一配置界面,保存自身领域相关的规则文件和事实结构,接收事实数据,驱动规则引擎执行规则。 - 痛点:要挖掘业务中心遇到的
复杂易变的痛点
,通过引入业务规则组件
, 变成高效响应的爽点
。业务规则组件及业务规则中心,才可能得到广泛的支持、推广和落地。为业务中心提供实质性
的助力,建议集中力量,攻克这些难点、痛点,现在的规则中心给业务中心的感觉,是要抢人家地盘或者就是来添麻烦的。