第 8 章 可靠性保障

8.1 可靠性模型

DTP 實作 必須 提供以下可靠性保障:

  1. 續傳:在底層連線中斷後恢復傳輸,不得 重傳已成功接收的資料。
  2. 確認:接收方 必須 向傳送方確認已成功接收的 Fragment。
  3. 重傳:傳送方 必須 在逾時未收到確認時重傳未確認 Fragment。
  4. 會話持久化:底層連線中斷時 必須 持久化會話狀態。

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 後 必須 嚴格遵循:

  1. 從下一個序列號繼續:從 highest + 1 開始重新傳送。
  2. 不重複傳送不得 重新傳送序列號 <= highest 的 Fragment。
  3. 不跳過不得 跳過未確認的 Fragment(即未在快取中確認接收的)。

8.3 確認機制

8.3.1 確認方式

實作 必須 提供 Fragment 接收確認。確認 透過以下方式之一實現:

  1. 顯式 ACK 控制訊框:接收方傳送 ControlFrame,controlType = "ack",details 包含已確認的最高序列號。
  2. 累積 ACK:在每個資料訊框的擴充欄位中攜帶反向方向的最高已接收序列號(推薦)。
  3. 批次 ACK:每接收 N 個 Fragment 傳送一次 ACK(實作定義 N,推薦 為 16)。

具體確認方式 由實作選擇,但接收方與傳送方 必須 就所選方式達成一致。

8.3.2 確認時序

接收方 必須 滿足:

  1. 在 Fragment 通過解密、Agreement 驗證、DAG 驗證後才能確認。
  2. 不得 在 DAG 處於 pending 狀態時確認(應在依賴解析後再確認)。
  3. ACK 中的最高序列號 必須 是已確認序列號集合的連續前綴的最大值。

8.4 重傳機制

8.4.1 重傳策略

傳送方 必須 在以下條件下重傳:

  1. 在協定配置的重傳逾時時間內未收到對應序列號的 ACK。
  2. 收到 ResumeReport 時,對未確認的 Fragment 重傳。

8.4.2 重傳配置

實作 提供以下可配置參數:

參數預設值(推薦說明
初始重傳逾時5 秒第一次重傳等待時間
重傳退避因子2每次重傳後逾時翻倍(指數退避)
最大重傳次數5超過後通知上層失敗
最大重傳逾時60 秒重傳逾時上限

實作 必須 實作指數退避演算法。

8.4.3 重傳失敗處理

當重傳次數超過上限時:

  1. 傳送方 必須 通知上層應用 RETRANSMISSION_TIMEOUT 錯誤(6002)。
  2. 傳送方 觸發會話暫停或終止(實作定義)。
  3. 實作 不得 無限重傳。

8.5 快取管理

8.5.1 未確認 Fragment 快取

傳送方 必須 維護未確認 Fragment 快取,滿足:

  1. 每個已傳送但未收到確認的 Fragment 必須 保留在快取中。
  2. 收到確認後,必須 從快取中移除已確認的 Fragment。
  3. 快取 必須 有容量上限(實作定義,推薦 不少於 1024 個 Fragment 或 16 MB)。

8.5.2 快取滿處理

當快取達到容量上限時,傳送方 必須

  1. 暫停傳送新 Fragment。
  2. 透過 BUFFER_FULL 錯誤(6001)通知上層應用。
  3. 在確認釋放快取空間後恢復傳送。
  4. 不得 靜默丟棄 Fragment。

8.6 會話管理

8.6.1 會話建立

CAP 完成身分驗證與金鑰交換後,DTP_Engine 必須 建立 DTP 會話:

  1. 必須 產生符合 RFC 4122 的唯一 Session_ID(UUID v4)。
  2. 必須 初始化 Session 資料結構(參見第 8.6.3 節)。
  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 必須

  1. 立即將 SessionState 從 Transmitting 轉換到 Suspended
  2. 持久化以下內容到非揮發性儲存:
    • 完整的 Session 物件(包括所有 active 約定)
    • 雙向 DirectionalTransferState
    • 未確認 Fragment 快取
  3. 持久化 必須 是原子的(要麼全部成功,要麼全部失敗)。

8.6.5 會話恢復

底層連線重新建立後,DTP_Engine 必須 遵循以下恢復流程:

  1. 等待 CAP 重新驗證。
  2. CAP 驗證成功後,進入 Resuming 狀態。
  3. 從持久化儲存中恢復 Session 狀態。
  4. 接收方傳送 ResumeReport(參見第 8.2.2 節)。
  5. 傳送方根據 ResumeReport 從中斷點繼續傳輸。
  6. 續傳交握完成後轉換到 Transmitting

如恢復失敗,DTP_Engine 必須

  1. 轉換到 Idle 狀態。
  2. 釋放所有相關資源。
  3. 透過 SESSION_RESTORE_FAILED 錯誤(5003)通知上層。

8.6.6 會話逾時

實作 必須 實作會話逾時機制:

  1. 必須 維護 lastActivityAt 欄位,記錄最後一次活動時間。
  2. now - lastActivityAt > timeoutThreshold 時,必須 將會話設為逾時。
  3. 逾時的會話 必須 被關閉,相關資源 必須 被釋放。
  4. 預設 timeoutThreshold 推薦 為 30 分鐘(1,800,000 ms)。

8.7 雙向獨立性

實作 必須 嚴格保證兩個傳輸方向的獨立性:

  1. 資料歸集方向的狀態變化 不得 影響資料注入方向。
  2. 一個方向的連線異常 不得 自動觸發另一個方向的狀態變更(除非底層連線整體中斷)。
  3. 一個方向的序列號 不得 進入另一個方向的序列號空間。
  4. 一個方向的快取 不得 佔用另一個方向的快取配額。