BLUEPRINT
第六章 数据传输
6.1 双向数据流
DTP 支持两个方向的数据传输,互不干扰:
| 方向 | 名称 | 说明 |
|---|---|---|
| Terminal → Fay | 数据归集 | 将终端产生的数据持久化存储到 Personal Data Heap |
| Fay → Terminal | 数据注入 | 经过 iFay 过滤和判断后的最小化数据集 |
两个方向使用相同的 Logical_Frame 格式和处理流程,但维护独立的序列号空间和续传状态。
6.2 数据归集流程(Terminal → Fay)
完整的数据归集流程经过以下步骤:
终端应用
│
▼ 提交数据
DTP_Slave Engine
│ 1. 附加上下文元数据
│ 2. 构建 LogicalFrame (Header + Payload)
│ 3. 加密 Payload
│ 4. 序列化 LogicalFrame
│
▼ send(binary_data)
Transport_Adapter
│
▼ onReceive(binary_data)
DTP_Master Engine
│ 1. 反序列化 LogicalFrame
│ 2. 验证 Agreement_ID
│ 3. 解密 Payload
│ 4. 验证 DAG 依赖
│ 5. 更新序列号 + 发送确认
│
▼ 存储
Personal Data Heap
6.3 数据注入流程(Fay → Terminal)
完整的数据注入流程经过以下步骤:
Personal Data Heap
│
▼ 查询并过滤数据
DTP_Master Engine
│ 1. 构建 Fragment + 上下文元数据
│ 2. 构建 LogicalFrame
│ 3. 加密 Payload
│ 4. 序列化 LogicalFrame
│
▼ send(binary_data)
Transport_Adapter
│
▼ onReceive(binary_data)
DTP_Slave Engine
│ 1. 反序列化 LogicalFrame
│ 2. 验证 Agreement_ID
│ 3. 解密 Payload
│ 4. 更新序列号 + 发送确认
│
▼ 交付数据
终端应用
6.4 Agreement_ID 压缩传输
为减少传输开销,DTP 支持 Agreement_ID 的压缩传输:
- 当连续的 Fragment 属于同一约定时,仅在该批次的首个 Fragment 头部携带完整的 Agreement_ID
- 后续 Fragment 的 agreementId 字段设为 null,表示沿用上一个
接收方处理规则:
- 收到携带 Agreement_ID 的 Fragment → 更新当前上下文的 Agreement_ID
- 收到未携带 Agreement_ID 的 Fragment → 关联到当前上下文中最近一次声明的 Agreement_ID
- 收到引用了未知 Agreement_ID 的 Fragment → 丢弃并发送错误通知
示例:
Fragment 1: agreementId = "abc-123" ← 完整 ID
Fragment 2: agreementId = null ← 沿用 "abc-123"
Fragment 3: agreementId = null ← 沿用 "abc-123"
Fragment 4: agreementId = "def-456" ← 新约定,完整 ID
Fragment 5: agreementId = null ← 沿用 "def-456"
6.5 序列号管理
单调递增
每个 Fragment 携带传输序列号(Sequence_Number),在单次会话内单调递增。
双向独立
数据归集方向和数据注入方向维护完全独立的序列号空间:
数据归集方向 (collection): seq 1, 2, 3, 4, 5 ...
数据注入方向 (injection): seq 1, 2, 3, 4, 5 ...
一个方向的序列号变化不影响另一个方向。
6.6 原始时间戳保全
DTP 确保每个 Fragment 的原始时间戳(Origin_Timestamp)在整个传输过程中保持不变:
- 记录数据在源端实际产生的时刻,而非传输时刻
- 使用 UTC 时区和毫秒级精度
- 经过序列化、加密、传输、解密、反序列化后,时间戳与发送前完全一致
- 接收方保留原始的 Origin_Timestamp 不做修改
这确保了即使数据延迟上传(如离线场景),iFay 也能还原真实的时间线。
6.7 DAG 依赖验证
接收方在接收 Fragment 时进行 DAG 依赖验证:
- 环路检测:验证新 Fragment 的依赖关系不会在 DAG 中形成环路。若检测到环路,拒绝该 Fragment
- 依赖解析:若依赖目标 Fragment 尚未到达,将当前 Fragment 标记为"依赖待解析"状态并缓存
- 延迟解析:当被依赖的 Fragment 到达后,自动解析之前缓存的 Fragment
