題幹與適用場景
你負責付款、改密碼或建立訂單 API。入口啟用 TLS 1.3 0-RTT,閘道可能把帶有 Early-Data: 1 的請求轉送給服務。請說明何時回傳 425、何時繼續處理,以及用戶端如何在握手完成後重試。題目適合後端、平台與 API 基礎設施職位。
RFC 8470 定義 425 是服務端不願冒險處理可能被重播的請求;它不是「服務太忙」的通用重試碼。以下假設閘道能保留 Early-Data 訊號,服務能區分唯讀請求與有副作用請求。
面試官考察點
- 能否把 0-RTT 的效能收益與重播風險分開,而不是把所有 4xx 都當成用戶端輸入錯誤。
- 能否沿著用戶端、閘道、應用程式三段資料流說明誰負責等待、重試與冪等。
- 能否指出 RFC 對 425 的發出條件、不可快取性與重試時機,並轉成可測試的 API 策略。
普通回答只背出「425 是 Too Early」。強回答會按副作用、Early-Data 標記、冪等鍵與重試窗口做決策,並說明錯誤設定如何造成重複扣款。
回答前需要澄清的問題
- 請求是否帶
Early-Data: 1,或入口是否能證明它來自早期資料?RFC 建議服務沒有這些訊號時不要任意回傳 425。 - 操作是否有外部副作用?讀取訂單可以繼續;扣款、改密碼與發券需要等待握手,或先建立嚴格的冪等狀態。
- 閘道是否會自動重試?若會,必須確認它在握手完成後重試,且不會讓應用程式與閘道各自重試一次。
- 用戶端是否支援冪等鍵與重試上限?沒有這些能力時,寧可關閉該類請求的 0-RTT,也不要把 425 當成無限重試許可。
30 秒回答框架
「我先確認請求是否來自帶有 Early-Data: 1 的 TLS 早期資料,再判斷它是否有副作用。唯讀請求可以繼續;付款、改密碼等寫入請求先回傳 425,或在閘道等待握手。用戶端只在握手完成後重試,服務端以冪等鍵與唯一約束避免重複執行。閘道要保留訊號、避免雙重重試,並監控 425 比例、重試成功率與重複副作用。若鏈路無法證明這些條件,我會關閉該端點的 0-RTT。」
分步驟深入解答
1. 先辨識風險訊號
RFC 8470 要求中間層在收到早期資料時保留 Early-Data 語意;服務端只有在請求可能被重播時才應考慮 425。沒有訊號卻回傳 425,會把一般網路失敗誤報成安全拒絕。
2. 按副作用分類
把端點分成唯讀、可安全重複與不可安全重複三類。GET /orders/123 通常是唯讀;產生一次性優惠券、扣款與修改密碼屬於不可安全重複。後者應等待完整握手,或由應用程式在持久層先記錄冪等鍵。
3. 規定單一重試責任
用戶端收到 425 後,必須等待 TLS 握手完成,再送出同一請求;重試不能再次走早期資料。閘道可以代為重試,但要把責任寫入契約,避免閘道與 SDK 同時重試。設定指數退避、次數上限與可觀測的重試原因。
4. 把冪等作為第二道防線
寫入請求要求用戶端產生冪等鍵。服務端以租戶、端點與鍵建立唯一記錄,狀態至少區分處理中、成功與可重試失敗;相同鍵再次抵達時回傳原結果或明確的處理中狀態。冪等鍵不能取代 425,因為首次處理仍可能在資料庫提交後、回應前被重播。
5. 處理閘道與多實例一致性
所有實例都要使用同一 Early-Data 策略。閘道若不確定上游是否理解該訊號,應等待握手或直接拒絕;不能把早期寫入請求靜默轉給只識別普通 HTTP 的服務。日誌記錄請求 ID、Early-Data、425 原因與冪等鍵雜湊,避免記錄付款內容。
6. 驗證失敗路徑
測試帶與不帶 Early-Data: 1 的請求、握手完成後的首次重試、閘道自動重試、用戶端逾時後再次提交,以及兩個實例並行處理同一冪等鍵。斷言不可重複副作用只發生一次,且 425 不被快取。
替代方案是完全關閉 0-RTT:安全邊界簡單,代價是增加首個請求的握手延遲。若端點數量少、延遲收益不重要,關閉往往比維護跨層策略更穩妥。
高品質示範回答
「我不會把 425 當成一般限流錯誤。先看請求是否帶 Early-Data: 1,再看操作是否有副作用。訂單查詢可以繼續;付款和改密碼在閘道等待握手,或由服務回傳 425。用戶端收到後只能在握手完成後重試一次,SDK 的上限與退避要寫入契約。服務端還要求冪等鍵,資料庫用租戶加鍵做唯一約束,並保存處理中與最終結果,防止回應遺失導致重複扣款。所有閘道與實例採用同一規則,監控 425、重試成功率與重複執行告警。如果鏈路無法傳遞 Early-Data,我會關閉寫入端點的 0-RTT,而不是猜測請求是否安全。」
常見錯誤
- 把 425 當作 429 的替代品 → 觸發原因與用戶端動作不同 → 只在早期資料重播風險成立時使用 425。
- 所有請求都回傳 425 → 讀取請求被無謂阻塞,用戶端可能無限重試 → 按副作用分類並設定上限。
- 重試仍走 0-RTT → 重播窗口沒有關閉 → 明確要求握手完成後再送出。
- 只在應用程式內做冪等 → 閘道或另一個實例可能先執行副作用 → 在入口、應用程式與持久層統一策略。
- 記錄完整付款內容排查重播 → 日誌暴露敏感資料 → 只記錄請求 ID、原因與脫敏後的冪等鍵。
追問及應對
如果閘道移除了 Early-Data 標頭,你如何處理?
我會把它視為能力缺失:閘道要麼等待握手後再轉送,要麼拒絕早期請求。應用程式不能從普通請求推斷它曾使用 0-RTT;先修復訊號傳遞,再啟用寫入端點。
如果用戶端在收到 425 前已逾時並再次提交呢?
用同一個冪等鍵接住兩次提交,第二次讀取第一筆的處理中或最終狀態。對沒有冪等鍵的危險寫入請求,回傳可診斷錯誤並進入人工或補償流程,不自動猜測是否已扣款。
如果重試成功率很高但延遲 SLO 變差,你會怎麼取捨?
按端點與用戶代理分段比較 425 率、p95 首次成功延遲、重複副作用與業務成功率。若寫入收益不足以抵銷延遲,我會只保留安全唯讀請求的 0-RTT,或直接關閉該類端點。