第2章:系统架构设计——多能协同控制软件的总体架构、分层设计思想、核心模块划分

各位同学,咱们今天聊聊系统架构。说实话,我见过太多项目一开始就急着写代码,结果做到一半发现模块之间耦合得跟麻花似的,改一个地方崩一片。多能协同控制软件尤其如此——它要管电、热、冷、气多种能源,还要实时调度,架构要是没搭好,后面就是无底洞。

我个人习惯,做架构设计前先问自己三个问题:系统要解决什么问题?数据怎么流动?模块之间怎么解耦?想清楚了再动手。下面我就把这些年踩过的坑和总结的经验,掰开了讲给你听。

2.1 总体架构:三层两总线

先看一张我手绘的架构图,这是咱们课程的核心骨架。

多能协同控制软件总体架构(三层两总线) 应用层 人机交互界面 调度策略管理 报表与告警 场景配置 历史数据查询 权限管理 服务层(核心引擎) 协同优化调度 预测与态势感知 安全校核 数据融合 规则引擎 日志与监控 数据层 实时数据库 历史数据库 模型库 时序数据 配置数据 告警数据 数据总线(消息队列) 服务总线(API网关)

这张图我称之为「三层两总线」架构。为什么这么画?我在项目里吃过亏——早期版本把数据访问和业务逻辑混在一起,结果换一个数据库类型,改了整整两周。后来痛定思痛,强制分层,世界清净了。

核心原则:上层依赖下层,下层绝不反向依赖上层。每一层只通过总线与相邻层通信。

2.2 分层设计思想:为什么非分不可?

你想想看,一个多能协同系统里,可能有光伏、储能、燃气轮机、热泵、冷机……每种设备的通信协议、数据格式都不一样。如果不分层,代码会变成什么样?

我见过一个真实案例:某项目把设备驱动、业务逻辑、界面渲染全写在一个类里,3000多行。后来要新增一种储能设备,开发人员改了三天,改出了五个bug。这就是典型的「大泥球」架构。

分层的好处,说白了就三点:

  • 隔离变化:换设备驱动不用动调度算法,换数据库不用动界面
  • 便于测试:每一层都可以单独写单元测试,我习惯先测服务层,再测数据层
  • 团队协作:前端团队、算法团队、数据团队各管一层,互不干扰

嗯,这里要注意:分层不是越多越好。我见过有人分了七层,结果一个简单的数据查询要穿越五六个接口,性能惨不忍睹。咱们这个系统,三层刚刚好。

2.3 核心模块划分:各司其职

下面我把每一层里的核心模块拆开讲。这些都是我在实际项目中反复验证过的。

2.3.1 数据层——系统的「记忆体」

数据层负责所有数据的存取。别小看它,多能协同系统的数据特点是:高频、多源、异构

数据类别 存储方式 典型数据 更新频率
实时数据 内存数据库(Redis) 电压、电流、功率、温度 毫秒级
历史数据 时序数据库(InfluxDB) 日发电量、负荷曲线 秒级
模型数据 关系数据库(PostgreSQL) 设备参数、拓扑结构 低频更新
配置数据 文件系统 + 数据库 调度策略、阈值设置 按需更新

我曾经犯过一个错:把所有数据都塞进关系数据库,结果实时数据写入太频繁,把数据库搞崩了。后来改用时序数据库存高频数据,关系库只存配置和模型,问题迎刃而解。

我的建议:实时数据用Redis做缓存,历史数据用时序库,别混着用。这是血的教训换来的。

2.3.2 服务层——系统的「大脑」

服务层是核心中的核心。我把它拆成五个模块:

  1. 协同优化调度模块:这是灵魂。它根据负荷预测、电价信号、设备状态,算出最优的能源分配方案。说白了,就是决定「什么时候用光伏、什么时候用储能、什么时候买电」。
  2. 预测与态势感知模块:负责预测未来15分钟到24小时的负荷和新能源出力。我用过LSTM、Transformer,也用过传统的时间序列方法。没有银弹,得看数据特点。
  3. 安全校核模块:调度方案算出来之后,得检查会不会导致电压越限、线路过载。我见过一个项目没做安全校核,调度指令下发后变压器直接跳闸……
  4. 数据融合模块:不同设备的数据格式、时间戳可能不一致。这个模块负责清洗、对齐、插值。脏数据进,干净数据出。
  5. 规则引擎模块:有些场景不需要复杂优化,比如「光伏功率超过80%时,自动启动储能充电」。这种规则用规则引擎处理,比写死代码灵活得多。

注意:服务层模块之间不要直接调用。我建议通过消息队列异步通信。比如调度模块算完方案后,发一条消息给安全校核模块,校核通过后再发消息给执行模块。这样即使某个模块挂了,系统还能降级运行。

2.3.3 应用层——系统的「面孔」

应用层直接面对用户。我强调一个原则:应用层只做展示和交互,不做业务计算

举个例子:用户点击「一键优化」按钮,应用层只负责把请求发给服务层,然后把结果展示出来。千万别在界面里写优化算法——我见过有人这么干,结果浏览器卡死了。

应用层我一般分这几个功能:

  • 实时监控大屏:展示当前各能源系统的运行状态
  • 调度策略配置:让用户设置优化目标(比如「最低成本」还是「最低碳排放」)
  • 历史数据回放:查看过去某段时间的运行曲线
  • 告警管理:显示异常事件,支持确认和处理

2.4 模块间通信:总线是关键

三层架构搭好了,模块之间怎么说话?我推荐用消息队列 + REST API的组合。

  • 数据总线(消息队列):用于高频数据交换,比如实时数据采集、调度指令下发。我用过Kafka和RabbitMQ,小规模项目用RabbitMQ就够了。
  • 服务总线(REST API):用于低频、请求-响应式的交互,比如用户查询历史数据、修改配置。

为什么不用一种方案包打天下?因为实时数据需要低延迟、高吞吐,而API调用需要可靠性和事务支持。各司其职,才是工程之道。

2.5 避坑指南:我踩过的三个坑

最后,分享几个我亲身经历过的教训:

  • 坑一:一开始没做模块解耦,结果设备驱动升级时,影响了调度模块。后来我强制所有模块只通过总线通信,再也没出过类似问题。
  • 坑二:数据层用了单一数据库,实时数据写入把历史查询拖慢了。解决方案是读写分离,实时库和历史库分开。
  • 坑三:应用层直接调用了数据层的接口,绕过了服务层。结果业务逻辑散落在各处,维护成本飙升。后来我在代码审查里加了规则:应用层只能调服务层接口。

好了,系统架构这块就聊到这儿。记住一句话:架构设计不是一次性的,它需要随着业务演进不断调整。但分层、解耦、总线通信这几个原则,什么时候都不过时。


公众号:蓝海资料掘金营,微信deep3321