返回首页

平台架构

整体架构使平台的核心理念得以在技术层面落地实现。

核心理念

平台所依托的基本理念

用户便捷

  • 直观的现代 UI
  • 适应用户需求
  • 便于从其他平台迁移

快速开发

  • 清晰的项目逻辑
  • 便捷的数据管理
  • 互操作性

资源效率

  • 充分发挥硬件性能
  • 线性扩展
  • 为软件付费,在硬件上节省

架构核心原则

这些原则决定了系统的技术能力

架构特性

上述原则的技术实现带来以下能力

即时配置

在不中断或停止运行流程(或将停机降至最低)的情况下更改系统与数据配置,并支持协同开发。

冗余

支持多节点主动配置。正是该选项确保即使发生故障也能将停机降至最短(0-RTO)。当某个节点需要停用时,始终有其他节点可用。

大数据量

处理海量数据,包括在高负载条件下。数百万个对象、数千万个变量、数十亿个数值。

可控降级

当负载超过可用资源时,系统会丢弃最不重要的数据。在某些情况下,数据不会丢失,而是保留在队列中——待负载下降后再行处理。

线性扩展

可通过增加节点来扩展系统。所有不靠近核心的服务都可去中心化;靠近核心的服务以 SAA 模式运行。

多租户

能够为不同子系统和用户隔离独立空间(对象、服务)。其基础是成熟的基于角色的访问控制系统。

平台结构

在结构上,平台由三个环境组成:集中了全部关键功能与 API 的核心环境、运行环境和开发环境。

平台核心

  • 包含核心功能
  • 负责数据处理
  • 服务交互机制
  • 实现响应式架构
  • 实现安全体系

运行环境

  • 操作员的主要工具
  • 监控画面与控件
  • 趋势
  • 事件、报警与确认
  • 便捷的 UI/UX

开发环境

  • 开发者的主要工具
  • 成熟的开发环境
  • 支持矢量编辑器
  • 变更同步
  • 脚本

平台核心

交付平台的关键功能。

运行数据

  • 动态点位(变量)
  • 在内存中处理
  • 运行归档(缓存)
  • 负载与突发管理
  • 每节点最多 10,000,000 个点位

元数据

  • 非时间敏感数据
  • 弱动态
  • 配置、结构、层级
  • 与运行数据隔离
  • 存储于关系型数据库

数据归档

  • 长期数据存储
  • 时间序列格式(TSDB)
  • 存储于列式数据库
  • 压缩、降采样、循环记录
  • 访问速度慢于运行数据

核心数据结构

数据类型

  • 离散 — boolean
  • 整型 — integer
  • 模拟 — float
  • 字符串 — string

模型

  • 抽象结构
  • 复杂的嵌套层级
  • 模型由模型组成
  • 核心面向对象原则

对象

  • 基于模型
  • 多个实例
  • 结构上依赖于模型
  • 支持级联变更
更改模型会触发基于该模型创建的所有对象的级联变更。删除系统逻辑中所使用的变量可能导致不可预测的后果——此类更改必须谨慎规划,并事先通过备份或导出保存配置。

模型架构

数据通过模型和对象来描述:模型是抽象,对象是其实例。每个对象都作为独立的响应式实体运行。

模型与对象的构成方式

  • 模型是由简单类型变量和嵌套模型构成的抽象实体。
  • 可任意深度嵌套。
  • 对象严格基于模型创建,并完整复现其结构。
  • 不更改模型就无法更改对象的结构。
结构组合
复合模型「机组」
模型「泵」
状态 · bool转速 · float压力 · float
+
模型「阀门」
开启 · bool位置 · float

变量 → 模型 → 复合模型。

对象派生
对象继承
模型「泵」
抽象实体
泵 №1
实例
泵 №2
实例
泵 №3
实例

对象复现模型的结构。

级联变更: 对模型的更改会自动应用于基于该模型创建的所有对象。

响应式架构

  • 每个对象由自己的轻量级线程提供支撑
  • 这些线程是响应性的基础(N 个线程,M 个 CPU 核心)
  • 对象独立且并行地对变化作出响应
  • 此类线程的开销极小
  • 可扩展至每节点数百万个对象
  • 控制级联变更并防止循环
对象
由轻量级线程提供支撑
数百万个对象
每节点并行
Go · 协程
轻量级线程,开销极小

响应式架构

事件驱动架构(EDA)

事件

  • 事件是平台的动态对象
  • 作为对变量值变化的响应而创建
  • 只要满足创建条件,事件便保持活动状态
  • 条件由计算器定义
  • 在离散对象状态发生变化时发生
  • 例如,某对象监测温度
  • 当超过设定值时改变状态
  • 发生指定类型的事件
属性集合:
对象类别创建时间消息文本类别优先级活动标志确认标志确认人

报警与确认

  • 报警是位于优先级刻度顶部的一类事件(最关键的事件)
  • 可以定义多个不同严重程度的报警类别
  • 报警可触发视听效果以引起操作员注意
  • 操作员通过确认来表示已收到事件信息
  • 平台会记录具体由谁进行了确认

事件优先级排序

  • 优先级是一个数值,例如从 1 到 10
  • 为事件类别设置,用于定义其重要性和严重性
  • 数值越高,事件越关键
  • 报警被赋予最高优先级
分级与排序

优先级影响事件的顺序。类别可按优先级、可确认性和声音进行排序。

声音提示

声音在优先级最高的事件上播放——按顺序、以设定的间隔播放。

确认之前

信号会一直重复,直到出现更高优先级的事件或当前事件被确认。

优先级
1234567
消息
8910
报警

服务模型

面向服务架构(SOA)

核心可支撑三类服务

1234

核心服务(core)

  • 靠近核心的数据处理
  • 操作缓存数据
  • 基础服务
事件计算归档

接口驱动(edge)

  • 数据采集与预处理
  • 后处理与准备
  • 数据与控制命令的传输
EdgeETL/ELT

接口(API)

  • 对 API 的完全访问
  • REST 协议
  • 用于响应性和实时的 WebSocket
APIRESTWebSocket

过程控制协议

  • 支持开放协议
  • 支持专有协议
  • 支持特殊协议
NTPSNMPOPC UAModbusProfinet
BACnetMQTTIEC-60870IEC-61850

与 IT 系统对接

  • 与开放 API 对接
  • 与专有 API 对接
  • 通过总线对接
ZabbixTrassirPercoFindFace
AsteriskOrionProSyslog

完整的驱动和开放协议列表见 在首页.

计算模型

平台提供多种计算工具

计算器

  • 在响应式逻辑中运行
  • 当关联对象变化时
  • 功能有限
  • 在核心层运行

集群脚本

  • 复杂的算法计算
  • 基于变量的计算
  • 可扩展的功能
  • 能够处理核心之外的数据

信号模拟器

  • 信号生成
  • 按给定规律
  • 用于计算的参考信号
  • 用于测试与诊断

计算器

计算器的应用场景

  • 跟踪变量变化
  • 算术、比较、积分、条件运算
  • 逻辑计算
  • 浮动设定值的计算

计算器的调用方式

  • 计算器从逻辑变量中调用,在该变量中设置目标公式
  • 一旦满足所设条件,变量便切换到所需状态
  • 该状态定义目标事件(包括报警)

计算器运算

+×÷
><=
如果多重如果

浮动设定值

t →
过程量设定值(上限 / 下限)

集群脚本

用于计算器无法覆盖的复杂任务。

复杂逻辑

  • 任意控制逻辑
  • 现代 Lua 语言
  • 编译为字节码
  • 大量代码
  • 任意复杂度

算法库

  • 可创建库
  • 代码复用
  • 从脚本管理
  • 功能组控制
  • 与 DCS 对接

API 可用性

  • 访问整个平台 API
  • 可访问外部 API
  • 去中心化
  • 互操作性
  • 安全

为何选择 Lua

Lua 是一种轻量且快速的语言,语法上与过程控制工程师熟悉的 ST(Structured Text)非常接近。

轻量快速类似 ST过程控制工程师熟悉
同一个泵控制算法:
ST (Structured Text)
PROGRAM Control_Pump_Prog
VAR
// 变量初始化(相当于 Lua 中的 local)
waterLevel : REAL := 5.5; // 当前水位
tankMax : REAL := 10.0; // 最高水位
tankMin : REAL := 2.0; // 最低水位
pump : BOOL := FALSE; // 泵状态
alarm : BOOL := FALSE; // 报警状态
END_VAR
// 泵控制函数
IF waterLevel > tankMax THEN
pump := FALSE; // 关闭泵
alarm := TRUE; // 触发报警信号
ELSIF waterLevel < tankMin THEN
pump := TRUE; // 启动泵
alarm := FALSE; // 清除报警
END_IF;
END_PROGRAM
Lua
-- 变量初始化(相当于 VAR 块)
local waterLevel = 5.5 -- 当前水位
local tankMax = 10.0 -- 最高水位
local tankMin = 2.0 -- 最低水位
local pump = false -- 泵状态
local alarm = false -- 报警状态
-- 泵控制函数
local function controlPump()
if waterLevel > tankMax then
pump = false -- 关闭泵
alarm = true -- 触发报警信号
elseif waterLevel < tankMin then
pump = true -- 启动泵
alarm = false -- 清除报警
end
end

该对比以泵控制为例:光标在两个代码块中同步移动,高亮显示对应的行。将光标悬停在某一行上可手动对照。

在正确配置的环境下,可用 Lua 几乎以 ST 语法编写。总体而言,用现代专用工具在 ST、FBD 中开发的脚本可以轻松移植到 Lua。

模拟器信号

模拟器按给定规律生成变量值。

  • 可设定幅值与频率
  • 适用于模拟量与离散量变量
  • 可用作计算的参考信号
  • 用于诊断
模拟量
恒定
正弦
三角
锯齿
方波
随机
离散量
状态切换
恒定

集群模型

高可用的容错集群

集群节点

  • Symmetric Active-Active 集群
  • 热备
  • 一致性内存缓存
  • 专用互连
  • 负载均衡器
  • 每节点最多 10,000,000 个点位

互连

  • 节点之间的双向交换
  • 通道冗余
  • 安全的交换协议
  • 高吞吐量
  • 低延迟与低抖动
  • 可控降级

集群客户端

  • Active-Passive 模式
  • 主动的冗余连接
  • 自动故障切换(failover)
  • 用于网关,包括 API 网关
  • 用于承载驱动(RRW)
  • 用于承载 WebSocket(WS)

核心集群模型的互连示意图

核心
8
主机
16
集群互连
2
主机互连
2
分段
IC 01IC 02IC 03IC 04IC 05IC 06R01R02R03R04R05R06R07R08C01C02C03C04C05C06C07C08C09C10C11C12C13C14C15C16

网络安全

平台包含强大的访问控制系统。

访问控制

  • 基于角色的访问控制(RBAC)
  • 有限作用域令牌(TBAC)
  • 支持 IAM 访问管理系统(LDAP、Keycloak)
  • 对象级多租户

访问控制对象

  • 模型与对象
  • 驱动与服务
  • 脚本
  • 组件与监控画面

身份识别与 访问控制

在平台各层级内置访问管理,无外部依赖

内置

自有身份验证机制和基于角色的访问模型,无外部依赖。临时令牌。

RBACTBAC
LDAP

与企业目录集成,统一管理账户

LDAPActive Directory
Keycloak

外部身份提供方,支持单点登录和联合身份

SSOOAuth 2.0OpenID联合身份

导入、导出与备份

支持以多种格式高效交换项目数据

数据导出

  • 模型与对象
  • 事件与报警
  • 脚本
  • 驱动与服务
  • 组件与监控画面
  • 变量绑定
  • 角色与用户

数据导入

  • 简化项目创建
  • 需要一致的格式
  • 例如表格(xlsx、csv)或 xml
  • 可从第三方 API 导入
  • 完全或部分导入
  • 考虑版本管理
  • 需要一定的谨慎

备份

  • 按请求执行
  • 可响应式或按定时器执行
  • 可由脚本调用
  • 可立即分离导出
  • 针对本不应发生的故障的恢复手段
  • 支持第三方备份系统