SPECIFICATION
第 8 章 可靠性保障
8.1 可靠性模型
DTP 實作 必須 提供以下可靠性保障:
- 續傳:在底層連線中斷後恢復傳輸,不得 重傳已成功接收的資料。
- 確認:接收方 必須 向傳送方確認已成功接收的 Fragment。
- 重傳:傳送方 必須 在逾時未收到確認時重傳未確認 Fragment。
- 會話持久化:底層連線中斷時 必須 持久化會話狀態。
8.2 續傳機制
8.2.1 續傳協定
續傳 必須 基於序列號實現,遵循以下流程:
傳送方 接收方
| |
|-- Fragment (seq=1) -------------->| ✓ 接收
|-- Fragment (seq=2) -------------->| ✓ 接收
|-- Fragment (seq=3) -------------->| ✓ 接收
|-- Fragment (seq=4) ------- ✗ ----| 連線中斷
| |
| [連線恢復] |
| |
|<-- ResumeReport (highest=3) ------|
| |
|-- Fragment (seq=4) -------------->| 從中斷點繼續
|-- Fragment (seq=5) -------------->|
8.2.2 ResumeReport
接收方在連線恢復後 必須 傳送 ResumeReport,定義如下:
interface ResumeReport {
collectionHighest: SequenceNumber;
injectionHighest: SequenceNumber;
}
| 欄位 | 規範性要求 |
|---|---|
collectionHighest | 必須 為接收方在資料歸集方向上已成功接收的最高序列號 |
injectionHighest | 必須 為接收方在資料注入方向上已成功接收的最高序列號 |
如某方向尚未接收任何 Fragment,對應欄位 必須 為 -1 或實作定義的「未接收」標識值。
8.2.3 續傳一致性
傳送方收到 ResumeReport 後 必須 嚴格遵循:
- 從下一個序列號繼續:從
highest + 1開始重新傳送。 - 不重複傳送:不得 重新傳送序列號
<= highest的 Fragment。 - 不跳過:不得 跳過未確認的 Fragment(即未在快取中確認接收的)。
8.3 確認機制
8.3.1 確認方式
實作 必須 提供 Fragment 接收確認。確認 可 透過以下方式之一實現:
- 顯式 ACK 控制訊框:接收方傳送 ControlFrame,
controlType = "ack",details 包含已確認的最高序列號。 - 累積 ACK:在每個資料訊框的擴充欄位中攜帶反向方向的最高已接收序列號(推薦)。
- 批次 ACK:每接收 N 個 Fragment 傳送一次 ACK(實作定義 N,推薦 為 16)。
具體確認方式 可 由實作選擇,但接收方與傳送方 必須 就所選方式達成一致。
8.3.2 確認時序
接收方 必須 滿足:
- 在 Fragment 通過解密、Agreement 驗證、DAG 驗證後才能確認。
- 不得 在 DAG 處於
pending狀態時確認(應在依賴解析後再確認)。 - ACK 中的最高序列號 必須 是已確認序列號集合的連續前綴的最大值。
8.4 重傳機制
8.4.1 重傳策略
傳送方 必須 在以下條件下重傳:
- 在協定配置的重傳逾時時間內未收到對應序列號的 ACK。
- 收到 ResumeReport 時,對未確認的 Fragment 重傳。
8.4.2 重傳配置
實作 應 提供以下可配置參數:
| 參數 | 預設值(推薦) | 說明 |
|---|---|---|
| 初始重傳逾時 | 5 秒 | 第一次重傳等待時間 |
| 重傳退避因子 | 2 | 每次重傳後逾時翻倍(指數退避) |
| 最大重傳次數 | 5 | 超過後通知上層失敗 |
| 最大重傳逾時 | 60 秒 | 重傳逾時上限 |
實作 必須 實作指數退避演算法。
8.4.3 重傳失敗處理
當重傳次數超過上限時:
- 傳送方 必須 通知上層應用
RETRANSMISSION_TIMEOUT錯誤(6002)。 - 傳送方 應 觸發會話暫停或終止(實作定義)。
- 實作 不得 無限重傳。
8.5 快取管理
8.5.1 未確認 Fragment 快取
傳送方 必須 維護未確認 Fragment 快取,滿足:
- 每個已傳送但未收到確認的 Fragment 必須 保留在快取中。
- 收到確認後,必須 從快取中移除已確認的 Fragment。
- 快取 必須 有容量上限(實作定義,推薦 不少於 1024 個 Fragment 或 16 MB)。
8.5.2 快取滿處理
當快取達到容量上限時,傳送方 必須:
- 暫停傳送新 Fragment。
- 透過
BUFFER_FULL錯誤(6001)通知上層應用。 - 在確認釋放快取空間後恢復傳送。
- 不得 靜默丟棄 Fragment。
8.6 會話管理
8.6.1 會話建立
CAP 完成身分驗證與金鑰交換後,DTP_Engine 必須 建立 DTP 會話:
- 必須 產生符合 RFC 4122 的唯一 Session_ID(UUID v4)。
- 必須 初始化 Session 資料結構(參見第 8.6.3 節)。
- 必須 將狀態從
WaitingForCAP轉換到SessionEstablished。
8.6.2 會話狀態維護
DTP_Engine 必須 在會話期間維護雙向的傳輸狀態:
interface DirectionalTransferState {
currentSequenceNumber: SequenceNumber;
highestAcknowledgedSequenceNumber: SequenceNumber;
unacknowledgedFragmentCache: Map<SequenceNumber, Fragment>;
}
實作 必須 為每個傳輸方向維護獨立的 DirectionalTransferState:
| 方向 | 欄位名 |
|---|---|
| 資料歸集(Terminal → Fay) | collectionState |
| 資料注入(Fay → Terminal) | injectionState |
8.6.3 Session 資料結構
完整的 Session 結構 必須 包含:
interface Session {
sessionId: SessionID;
masterIdentity: string;
slaveIdentity: string;
state: SessionState;
activeAgreements: Map<AgreementID, Agreement>;
collectionState: DirectionalTransferState;
injectionState: DirectionalTransferState;
createdAt: number;
lastActivityAt: number;
timeoutThreshold: number;
}
8.6.4 會話持久化
當底層傳輸連線中斷時,DTP_Engine 必須:
- 立即將 SessionState 從
Transmitting轉換到Suspended。 - 持久化以下內容到非揮發性儲存:
- 完整的 Session 物件(包括所有 active 約定)
- 雙向 DirectionalTransferState
- 未確認 Fragment 快取
- 持久化 必須 是原子的(要麼全部成功,要麼全部失敗)。
8.6.5 會話恢復
底層連線重新建立後,DTP_Engine 必須 遵循以下恢復流程:
- 等待 CAP 重新驗證。
- CAP 驗證成功後,進入
Resuming狀態。 - 從持久化儲存中恢復 Session 狀態。
- 接收方傳送 ResumeReport(參見第 8.2.2 節)。
- 傳送方根據 ResumeReport 從中斷點繼續傳輸。
- 續傳交握完成後轉換到
Transmitting。
如恢復失敗,DTP_Engine 必須:
- 轉換到
Idle狀態。 - 釋放所有相關資源。
- 透過
SESSION_RESTORE_FAILED錯誤(5003)通知上層。
8.6.6 會話逾時
實作 必須 實作會話逾時機制:
- 必須 維護
lastActivityAt欄位,記錄最後一次活動時間。 - 當
now - lastActivityAt > timeoutThreshold時,必須 將會話設為逾時。 - 逾時的會話 必須 被關閉,相關資源 必須 被釋放。
- 預設
timeoutThreshold推薦 為 30 分鐘(1,800,000 ms)。
8.7 雙向獨立性
實作 必須 嚴格保證兩個傳輸方向的獨立性:
- 資料歸集方向的狀態變化 不得 影響資料注入方向。
- 一個方向的連線異常 不得 自動觸發另一個方向的狀態變更(除非底層連線整體中斷)。
- 一個方向的序列號 不得 進入另一個方向的序列號空間。
- 一個方向的快取 不得 佔用另一個方向的快取配額。
