# RMDC-exchange-hub Detailed Design Specification

### 项目划分说明

1. RMDC-exchange-hub(MQTTX) 是Server端
2. RMDC-watchdog是Client
    1. RMDC-watchdog RMDC-watchdog-agent RMDC-watchdog-node三者运行在外部环境,作为单个项目
    2. 下文简称RMDC-watchdog代表的是一个项目，单个项目与 RMDC-exchange-hub（MQTTX）不在同一个网络中，需要跨越公网交互
    3. 考虑到兼容性，假设所有的项目均只能单方面跨公网访问RMDC-exchange-hub（MQTTX）
    4. 有部分项目无法访问RMDC-exchange-hub（MQTTX）,是纯内网的环境
3. MQTTX是消息中间件
    1. 借用现有的消息中间件，处理单向网络环境下的指令 信息处理问题
    2. 解决队列消息持久化问题
    3. 整体信息流程为 RMDC-exchange-hub <-- MQTTX <-- RMDC-watchdog
    4. MQTTX <-- RMDC-watchdog是弱网络环境，保证信息传递的准确性
    5. RMDC-exchange-hub <-- MQTTX是网络质量很好

## 指令数据处理流程

### 指令数据流向说明

1. RMDC-watchdog向RMDC-exchange-hub（MQTTX）发送信息成为 上行
2. RMDC-exchange-hub（MQTTX）向RMDC-watchdog发送信息成为 下行

### 指令数据消息说明

1. RMDC-watchdog需要接收、上传多种不同模块的信息，并作出相应的解析
    1. 接收下行的command指令
        1. 授权信息
        2. 日志指令
        3. 主机执行
        4. k8s执行指令
        5. 业务更新指令
    2. 发送上行的消息message类别
        1. 监控信息
        2. 日志内容
        3. 主机执行结果
        4. k8s执行结果
        5. 业务更新结果
2. mqtt是明文传输的，敏感信息需要进行加密处理
3. RMDC-exchange-hub 维护项目在线状态，超时未心跳自动标记离线并告警

### 项目启动注册流程

#### 项目信息注册流程

1. 需要从 rmdc-project-management 创建项目的信息
    1. 项目的名称
    2. 项目的命名空间
    3. 项目ID Project_ID
        1. 生成规则为 命名空间_<8位小写字符数字随机数>
    4. 项目的一级授权密钥 tier_one_secret
    5. 项目的一级授权密钥时间偏移值 time_offset_allowed 单位秒
    6. 项目的授权有效期 authorization_duration 单位天
    7. 项目的授权类型 authorization_type 永久授权或者时效授权
    8. 项目的二级授权密钥 tier_two_secret

#### 正常的rmdc-watchdog启动流程

1. 需要根据 rmdc-project-management 创建的信息启动程序
    1. 见上文
    2. 项目ID使用项目信息中的，不在rmdc-watchdog中生成
2. 采用“挑战-应答”机制，确保边缘节点合法性 正常的流程如下
    1. 尝试连接MQTTX，创建如下的Topic
        1. 发送Topic
            1. wdd/RDMC/command/up
            2. wdd/RDMC/message/up
        2. 接收Topic
            1. wdd/RDMC/command/down/<project_id>
            2. wdd/RDMC/message/down/<project_id>
    2. 发送上行注册command信息, 到wdd/RDMC/command/up，包含项目的所有信息
        1. 信息需要加密
    3. RMDC-exchange-hub（MQTTX）解析注册command
        1. 需要调用 rmdc-project-management 的接口
            1. 验证项目信息的合法性
            2. 验证项目的一级TOTP密码是否正确 (开关功能,可以不强制)
        2. 发送下行 注册成功message到 wdd/RDMC/message/down/<project_id>
            1. 附加 随机信息, 32位随机小写字母+数字
        3. 发送下行 注册command到 wdd/RDMC/command/down/<project_id>
            1. 验证项目的一级TOTP密码是否正确 (开关功能,可以不强制)
    4. RMDC-watchdog获取下行的注册 command和message
        1. 成功接收到message,解析其中的随机信息
        2. 接收到command之后
            1. 组装message中的随机信息为新的上行Message
            2. 发送上行Message到 wdd/RDMC/message/up
    5. RMDC-exchange-hub（MQTTX）解析到该项目的注册成功Message
        1. 验证随机信息的正确性
        2. 代表该项目初始化连接成功

#### rmdc-watchdog无法连接到MQTTX的流程

1. 仍然保持项目信息注册流程

### Command Message 生命周期与持久化流程

#### Command生命周期

1. 指令的生命周期流程指的是
    1. 指令从从业务模块来，包含模块名称，包含指令类型，包含业务下发人
    2. 指令包装成command消息，生成指令唯一ID
    3. 指令发送至MQTTX，记录指令下发时间戳
    4. 指令从MQTTX下发到RMDC-watchdog，记录指令接收时间戳
    5. 指令从RMDC-watchdog下发到执行体
    6. 指令从执行体返回到RMDC-watchdog
    7. RMDC-watchdog将指令转换为Message消息
    8. 消息从RMDC-watchdog返回到MQTTX， 记录消息上行时间戳
    9. 消息从MQTTX返回到RMDC-exchange-hub，记录消息返回时间戳
    10. 追踪计算每一阶段的耗时
        1. 指令下发耗时 = 指令接收时间戳 - 指令下发时间戳
        2. 指令执行耗时 = 消息上行时间戳 - 指令接收时间戳
        3. 指令上行耗时 = 消息返回时间戳 - 消息上行时间戳
    11. 消息从RMDC-exchange-hub返回到业务模块
2. 利用类似状态机的形式追踪指令的生命周期
3. 指令消息生命周期生命体
    1. 业务模块名称
    2. 指令类型
    3. 项目ID
    4. 指令下发人
    5. 指令下发时间
    6. 指令唯一ID，构建方式为 <指令类型>-<项目ID>-<时间格式 yyMMddHHmmss>
    7. 异步或者同步指令
4. 异步和同步指令，如果实现困难，与现有架构冲突，暂时不用实现
    1. 异步指令
        1. 指令下发之后，不等待回复
        2. 指令消息返回之后
            1. 直接入库
            2. 可以通过 rmdc-notice-center 进行消息通知
    2. 同步指令
        1. 指令下发之后，等待回复
        2. 指令消息返回之后
            1. 直接返回给调用的业务模块
            2. 入库
            3. 也可以进行消息通知

#### Command 生命周期持久化
1. 指令的生命周期持久化
    1. 负责指令生命周期的持久化
        1. 指令的完整信息保存
        2. 指令对应回复Message信息保存
    2. 优化数据库存储结构
        1. 能够快速查询到指令的完整信息 以及 指令对应的Message回复信息
        2. 能够快速查询到指令的回复信息
    3. 指令回复消息需要持久化
2. 下行指令 Command 持久化
    1. 每条下发的指令Command 都应该持久化保存
3. 接收上行 Message 持久化
    1. 每条接收的上行Message 都应该持久化保存
    2. 优化Message的存储
        1. 日志类型信息上行，不保存日志的详细内容
        2. 监控类型信息上行，不保存监控的详细内容，由rmdc-monitor-center进行持久化

### 指令下行 处理流程

1. 参考Command生命周期

### 消息上行 处理流程

1. 消息上行存在两种情况
    1. 指令回复消息
    2. 心跳及监视消息上行
2. 指令回复消息
    1. 指令回复消息需要持久化
    2. 此类消息需要与指令生命周期进行关联
    3. 此类消息处理之后，需要返回至原业务调用模块
3. 项目心跳消息上行
    1. 项目心跳消息需要持久化，参考 MQTTX状态及项目在线状态
4. 监视消息上行
    1. 监视消息上行需要发送给 rmdc-monitor-center

### 模块前端展示

1. 指令查询展示,支持筛选,查询,导出
    1. 指令的生命周期展示
    2. 指令的执行结果展示
    3. 指令的执行日志展示

## MQTTX状态及项目在线状态

1. 需要提供项目在线状态查询接口，特定时间段的在线状态
2. 需要提供MQTTX在线状态查询接口，特定时间段的在线状态

### 存活连接状态持久化

1. 采用时序数据存储类型
2. MQTTX状态持久化展示
    1. rmdc-exchange-hub项目启动时候，创建MQTTX在线状态表
    2. rmdc-exchange-hub需要每5分钟检查MQTTX的状态
    3. 检测到MQTTX在线，则更新MQTTX在线状态表
    4. MQTTX离线，不需要更新，状态表应该默认该时间点不在线
3. 项目在线状态持久化展示
    1. rmdc-watchdog项目注册时候，为该项目创建项目在线状态表
    2. rmdc-watchdog需要定期发送心跳存活信息
    3. 检测到心跳信息，则更新项目在线状态表
    4. 项目离线，不需要更新，状态表应该默认该时间点不在线

### 模块前端展示

1. 所有项目的连接状态查看
    1. 能够查看单个项目的具体连接内容
    2. 展示能够查看所有项目的连接状态
    3. 能够统计单个项目的离线次数
    4. 可以利用时序数据存储,然后做成uptime的前端监视页面
        1. 展示一段历史时间内的在线状态,在线就是绿色,离线就是红色
        2. 展示在线时间段支持调节
2. 查看MQTTX的状态
    1. 查看MQTTX的历史存活状态
    2. 查看MQTTX的历史消息数量
    3. 查看MQTTX的实时消息数量
    4. 查看MQTTX的队列数量等
    5. 

## 消息报文与安全要求

1. **统一报文包装**：`message_id`(UUID)、`type`(command/data)、`project_id`、`timestamp`(ms)、`version`、`payload`(JSON)、`signature`(HMAC-SHA256)、`encrypted`(bool)、`retry_no`(int)。
2. **敏感字段加密**：授权文件/TOTP/主机账号/业务密钥使用 AES-256-GCM，加密后仍需签名。
3. **幂等与去重**：按 `message_id + project_id` 去重，重复上行直接 ACK，不重复写库。
4. **访问控制**：所有下行指令需验证调用方权限（业务模块→exchange-hub），所有上行需验证签名+TOTP（开关）。

## 可靠性与重试策略

1. **QoS**：上下行默认至少一次（At-Least-Once），前端/业务模块需幂等。
2. **ACK/超时**：指令下发等待 watchdog ACK，默认超时 30 秒、重试 3 次，超时进入告警并记录审计。
3. **指令追踪**：`command_tracker` 记录 sent_at/acked_at/started_at/completed_at，`command_result` 记录 start_time/end_time/duration/received_at，缺失字段展示为 NA。
4. **断线补传**：watchdog 缓存最近 N 条结果，重连后批量上报；exchange-hub 支持批量 up 消息，需按 message_id 去重。

## 异常与降级

1. **错误码**：`EXH-4xx`（参数/鉴权），`EXH-5xx`（内部错误），`EXH-MQTT-xxx`（MQTT 通道异常），`EXH-AUTH-xxx`（授权/签名/TOTP 异常）。
2. **降级通道**：MQTT 不可用时开启 HTTP 临时通道（同样签名+TOTP），仅允许 register/auth/exec_result，其他指令暂停。
3. **安全告警**：签名/TOTP 失败触发 notice-center 告警并写审计。
