如何測試代理鏈路中的 HTTP/2 GOAWAY 排空

木版畫風格的網際網路資料流從正在排空的 HTTP/2 連線平穩切換到新路徑

一條 HTTP/2 連線可以同時承載許多請求。端點送出 GOAWAY 時,不只是表示「Socket 出錯」,而是在宣告連線即將退役,並提供可能已處理到的串流邊界。客戶端若忽略這個邊界,可能繼續把新工作放到即將關閉的連線上,導致請求遺失,甚至重複執行不可重放的寫入。

本指南用來驗證經過代理的 HTTP/2 路徑:收到 GOAWAY 後,舊連線不再接收新串流;符合條件的進行中串流可以完成;新工作切換到替代連線;只有語意與串流證據都允許的請求才會自動重試。

正確理解 GOAWAY 證據

記錄錯誤碼、最後串流識別碼、接收時間、連線識別碼與每個串流狀態。高於最後串流識別碼的串流可視為未被發送方處理;低於或等於該識別碼但尚未完成的串流則有歧義,因為部分資料可能已交給上層應用程式。

不要把策略簡化成「失敗就全部重試」。讀取請求可能符合自動重試政策;建立訂單、啟動工作或扣款的 POST 若沒有回應,不代表可以安全重放。即使使用冪等鍵,也要確認目的端確實會強制去重。

建立隔離測試環境

只使用自有或已獲授權的目的端與代理線路。測試來源站至少提供快速讀取、延遲讀取、具伺服器端冪等鍵的寫入、沒有重放保護的寫入,以及可核對的請求與連線識別碼。

客戶端需要輸出連線 ID、串流 ID、分配時間、標頭送出時間、回應狀態、完成結果與重試決策。代理日誌應移除憑證與可能含個人資料的回應內容。

建立基準

經由代理開啟一條 HTTP/2 連線,同時送出快速、延遲與寫入請求。先確認請求確實多工在同一連線上,並確認來源站只執行一次每個操作。

記錄正常情況的 p50、p95 完成時間、新連線建立時間與穩定併發量。沒有基準,排空測試很容易把一般延遲誤判為關閉異常。

觸發優雅排空

先啟動多個延遲串流,再讓受控端點送出帶 NO_ERROR 的 GOAWAY。在最後串流識別碼以內保留部分進行中串流,並在訊框到達後立即嘗試安排新工作。

合格行為應包括:

  1. 舊連線立即進入 draining 狀態;
  2. 不再向舊連線分配新串流;
  3. 符合條件的進行中串流在限定時間內完成;
  4. 新工作改用替代連線;
  5. 明確未處理的串流進入相應重試分類;
  6. 有歧義的非冪等操作進入核對流程,而非盲目重放。

接著降低最後串流識別碼,使數個剛建立的串流落在邊界之外;再測試錯誤型 GOAWAY,以及送出訊框後立即中斷連線的情境。客戶端不能假設每次排空都能正常結束。

覆蓋危險時序

加入受控抖動並重複執行:GOAWAY 在標頭送出前抵達、在標頭後但請求本文未完成時抵達、在回應本文串流傳輸期間抵達、連續兩個 GOAWAY 且第二個邊界更低、排空期限前連線中斷、替代連線的驗證或 TLS 檢查失敗,以及大量工作執行緒同時觀察到 GOAWAY。

確認併發不會放大成重試風暴。同一路由或連線池只應產生受控的替代連線嘗試。重試上限可參考代理重試預算指南,連線壽命邊界可搭配代理閒置逾時與 Keep-Alive 測試驗證。

預先定義重試分類

請求類型 | 串流證據 | 自動動作
冪等讀取 | 明確未處理 | 在預算內重試
冪等讀取 | 狀態有歧義 | 僅依書面政策重試
受保護寫入 | 明確未處理 | 使用同一強制冪等鍵重試
受保護寫入 | 狀態有歧義 | 先依冪等鍵核對
無保護寫入 | 存在任何歧義 | 不自動重放

傳輸層重試、應用程式重試與業務核對必須分開。程式庫預設值不能取代業務安全政策。

關鍵驗收指標

  • GOAWAY 後分配至舊連線的新串流數必須為零;
  • 符合條件的進行中串流完成率;
  • 替代連線建立時間;
  • 依請求類型與原因統計的重試量;
  • 重複副作用必須為零;
  • 孤立或無人追蹤的操作數量;
  • 每個原始請求造成的重試放大倍數;
  • 排空時間與強制關閉次數;
  • 未受影響連線與路由的成功率。

依代理協定、出口市場、客戶端執行環境、程式庫版本、IPv4/IPv6、黏性或輪換工作階段分組。輪換路由在新連線更換出口可能符合預期;黏性工作階段則可能需要新的工作階段權杖或明確的連續性檢查。

上線檢查清單

  • GOAWAY 有獨立事件類型,不會合併成一般連線錯誤。
  • 去識別化日誌包含連線與串流識別碼。
  • 排空連線不再接收新串流。
  • 進行中請求有明確且有限的完成窗口。
  • 替代連線建立會合併並限速。
  • 重試依據請求語意、串流證據與冪等控制。
  • 不安全或有歧義的寫入進入業務核對。
  • 重複故障注入下仍無重複副作用。
  • 重試放大維持在預算內。
  • IPv4、IPv6 與目標市場分別測試。
  • 憑證不會進入追蹤資料或測試夾具。
  • 回復可以停用自動重放,而不需中止全部流量。

常見問題

GOAWAY 一定代表錯誤嗎?

不一定。NO_ERROR 常用於優雅退役,其他錯誤碼可能代表協定或內部故障。無論哪一種,邊界生效後舊連線都不應再接收新串流。

所有高於最後串流識別碼的請求都能重試嗎?

傳輸證據表示送出 GOAWAY 的對端未處理這些串流,但仍需遵守業務期限、驗證、冪等鍵與重試預算。

新連線要等舊連線完全關閉後再建立嗎?

通常不用。新工作應切換至替代連線,同時讓舊串流在限定時間內完成;但要限制替代連線併發,避免全域排空引發連線風暴。

代理上游若使用 HTTP/1.1 怎麼辦?

分別驗證兩端可觀察的行為。客戶端側的 GOAWAY 邊界仍然重要,而有歧義的寫入是否已執行,需要依靠來源站證據判斷。

合規說明

僅在已獲授權的系統、帳號、代理路由與資料範圍內執行排空與重試測試。遵守目的端條款、速率限制與隱私要求;使用合成資料、隱藏憑證,並只保留可靠性與稽核所需的證據。

來源說明:IETF,RFC 9113《HTTP/2》,2022 年 6 月。外部研究位址只保存在內部營運紀錄中。