Files
Inbox/系统基座文件/2/2.4/2.4.2 业务数据序列化规范 (Business Data Serialization Specification).md
2025-12-11 07:24:36 +08:00

143 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
tags: []
date created: 星期一, 十一月 24日 2025, 4:21:43 下午
date modified: 星期一, 十一月 24日 2025, 4:38:46 下午
---
# 2.4.2 业务数据序列化规范 (Business Data Serialization Specification)
## 1. 技术选型基线Protocol Buffers V3
- **基线决策**:继续沿用 **Google Protobuf v3**
- **论证**Protobuf 提供的 **Schema Evolution模式演进** 能力对于雷达这种生命周期长达数年的系统至关重要。它允许我们在未来添加新的字段(如“目标分类置信度”或“干扰源类型”)而不破坏旧版显控软件的兼容性。
## 2. 根消息结构定义 (Root Schema Definition)
基于 **TDP-2.4-DIST**(分布式补丁)和 **ECN-2025-001**(显控扁平化),我们需要对 `04_序列化与网络协议.md` 中定义的 `TrackDataBatch` 进行**重大升级**。
以下是最终确立的 `.proto` 契约:
```Protocol Buffers
syntax = "proto3";
package radar.ipc;
// 2.4.2 核心契约:原子业务数据批次
message TrackDataBatch {
// --- 传输层元数据 ---
// [分布式核心] 站点/阵面唯一标识 (Station ID)
// 必须由配置管理模块注入,用于显控端区分数据源
uint32 station_id = 1;
// [丢包检测] 批次序列号 (单调递增)
// 仅在单个 Station 内连续。显控端需按 StationID 分别统计丢包率。
uint64 batch_sequence_id = 2;
// [完整性] 全链路校验和 (CRC32c)
// 覆盖除本字段外的所有数据。
uint32 checksum = 3;
// --- 业务层元数据 ---
// [时序基准] 数据生成时间戳 (UTC Microseconds)
// 必须基于总控授时校正后的软时钟,严禁使用本地 Uptime。
// 显控端据此进行多站数据的时空对齐。
uint64 timestamp_us = 4;
// [可观测性] 全链路追踪 ID
// 继承自处理该 CPI 数据的 TraceContext
uint64 trace_id = 5;
// [流控状态] 当前节流等级 (反馈给显控端)
// 0=全速, 1=轻微, 2=严重。显控端可据此提示用户"当前数据已降级"。
uint32 throttle_level = 6;
// --- 业务负载 (Atomic Payload) ---
// 确认航迹 (高价值,节流时优先保留)
repeated TrackMessage tracks = 7;
// 原始点迹 (低价值,量大,节流时优先丢弃)
repeated PlotMessage plots = 8;
// 系统状态/心跳信息 (可选,用于带外健康监测)
SystemStatusMessage system_status = 9;
}
// 单个航迹定义 (精简版,详细物理含义见 02_核心数据结构.md)
message TrackMessage {
uint64 track_id = 1;
TrackStatus status = 2; // TENTATIVE, CONFIRMED, COAST, LOST
// 状态向量 (位置+速度)
// 建议统一使用 WGS84 (经纬高) 或 地心笛卡尔坐标 (ECEF)
// 以避免极坐标在分布式融合时的歧义
double pos_x = 3;
double pos_y = 4;
double pos_z = 5;
double vel_x = 6;
double vel_y = 7;
double vel_z = 8;
// 协方差矩阵 (可选,用于高级融合)
repeated float covariance = 9;
}
```
## 3. 序列化策略:原子批次 (Atomic Batch) Vs 微批次 (Micro-batch)
- **旧设计遗留问题**:在之前的设计讨论中(未实施),为了配合“抢占式调度”,曾考虑将一个 CPI 的数据切碎发送。
- **新基线 (ECN-2025-001)**
- **策略****原子批次 (Atomic Batch)**。
- **定义**:一个 Protobuf `TrackDataBatch` 消息 **严格对应一个雷达处理周期 (CPI)** 的所有产出物。
- **行为**`DisplayController` 等待 `DataProcessor` 输出完整的航迹列表后,一次性打包。
- **收益**:显控端逻辑大幅简化。收到一个包,就是一帧完整的态势图,无需处理“半帧”数据或进行复杂的跨包重组。
## 4. C++ 与 Protobuf 的映射效率优化
虽然 Protobuf 很快,但从 C++ `struct TrackData` 到 Protobuf `message TrackMessage` 的转换仍然涉及内存拷贝和遍历。为了在 100Hz+ 的刷新率下不成为瓶颈:
- **预分配 (Reserve)**:在构建 `TrackDataBatch` 时,根据 C++ `vector` 的大小,预先调用 Protobuf 的 `MutableRepeatedPtrField::Reserve()`,避免多次内存重分配。
- **移动语义 (Move Semantics)**Protobuf v3 在 C++ 中支持 `std::move`。如果序列化是在独立的 I/O 线程中进行(见 2.4.1),我们可以考虑直接接管数据所有权,但通常 Protobuf 生成的代码需要 Setter 拷贝。
- _优化技巧_对于包含大量数据的字段如点迹列表如果在 C++ 端也使用了类似 Protobuf 的内存布局(连续内存),可以使用 `Arena Allocation` 或自定义反射来加速,但在本系统中,**简单的字段赋值配合编译器优化(-O3通常已足够不必过度优化**。
## 5. 节流与数据剪裁 (Throttling & Pruning)
基于 **2.3.5 热节流控制**,序列化模块必须实现**内容感知剪裁**
```cpp
void DisplayController::serializeAndSend(const TrackDataPacket& packet) {
radar::ipc::TrackDataBatch pb_batch;
// 1. 填充元数据 (StationID, TraceID, Timestamp…)
// 2. 获取当前节流等级 (通过原子变量读取)
auto level = throttle_level_.load();
pb_batch.set_throttle_level(level);
// 3. 内容剪裁逻辑
if (level < 2) {
// Level 0/1: 发送全量数据
for (const auto& plot : packet.plots) { /* 转换点迹 */ }
}
// 始终发送航迹 (除非 Level 3 暂停)
for (const auto& track : packet.tracks) { /* 转换航迹 */ }
// 4. 序列化并发送
// …
}
```
---
# 总结2.4.2 基线图谱
| **规范项** | **核心基线** | **变更说明 (vs 旧文档)** |
| ------- | ----------------------- | ------------------- |
| **格式** | **Protobuf v3** | 保持不变。 |
| **标识** | **StationID + TraceID** | 新增 StationID 支持分布式。 |
| **时序** | **UTC Timestamp** | 取代本地时间,支持总控同步。 |
| **粒度** | **Atomic CPI Batch** | 废弃微批次,简化接收端逻辑。 |
| **流控** | **内容剪裁 (Pruning)** | 根据节流等级动态丢弃 Plot 字段。 |