後端面試:如何用 HTTP Priority 設計資源排程策略?
題干與適用場景
一個頁面同時請求 HTML、關鍵 CSS、字型、圖片與背景資料。行動網路頻寬有限,團隊希望用 HTTP Priority 讓關鍵資源更早完成,卻擔心代理覆寫優先級、低優先級請求飢餓、快取命中繞過排程,以及丟包重傳改變順序。請設計伺服器與代理的排程策略,涵蓋 HTTP/1.1、HTTP/2、HTTP/3 與驗證方案。
RFC 9218 定義與協定版本無關的 Priority 標頭,也定義 HTTP/2 和 HTTP/3 的重新排序 frame。它表達客戶端和伺服器的偏好,不是必須遵守的交付承諾。強回答會把訊號、排程器、快取與傳輸層分開,並說明每一層可以拒絕或改寫什麼。
面試官考察點
- 是否知道 urgency 範圍是 0 到 7,數字越小優先級越高,請求預設值為 3。
- 是否能解釋 incremental 對同一 urgency 資源的並行分片與完成時間影響。
- 是否區分 HTTP/1.1 的順序請求與 HTTP/2、HTTP/3 的多路複用排程。
- 是否把 Priority 當提示而非 SLA,並處理惡意或錯誤客戶端的優先級宣告。
- 是否考慮快取命中、代理重排、QUIC 重傳、公平性與跨連線競爭。
- 是否能設計可回退的灰度和按使用者體驗結果驗收的指標。
回答前需要釐清的問題
- 目標是降低首屏 LCP、縮短某個 API 尾延遲,還是提高背景吞吐?目標不同會改變優先級和指標。
- 資源是否同一連線、同一 CDN 節點和同一快取鍵?跨連線時單連線優先級無法直接比較。
- 哪些資源能增量處理?CSS、完整字型和不可分塊的壓縮物件通常不應只因高 urgency 就並發切片。
- 代理是否允許轉送請求標頭、回應標頭和 PRIORITY_UPDATE?所有鏈路是否使用 HTTP/2 或 HTTP/3?
- 是否有租戶、使用者或安全邊界,防止低價值請求偽裝成最高優先級?
30 秒回答框架
我會先把目標定為使用者可感知的完成時間,再給資源分類與預設優先級。客戶端的 Priority 只作為輸入,伺服器按資源類型、快取狀態、連線與公平性重新計算。urgency 0 到 7 表達相對順序,incremental 只給能邊到邊處理的回應。HTTP/1.1 採用連線內請求順序,HTTP/2 和 HTTP/3 使用排程器及必要的重新排序 frame。快取命中、重傳和跨連線頻寬另行處理。灰度時同時觀察 LCP、關鍵資源完成時間、背景尾延遲、飢餓比例和頻寬,異常就關閉改寫策略。
分步驟深入解答
1. 先把業務目標轉成排程目標
首屏 HTML、阻塞渲染的 CSS 和關鍵字型追求盡快完成;大圖片可低一些 urgency;分析上報與預取應避免爭搶;背景 API 不能因使用者看不見就無限等待。為每類資源定義最大等待時間和可接受頻寬份額,不要只寫「關鍵請求優先」。
2. 解釋 Priority 兩個參數
u 是 urgency,0 最高、7 最低,客戶端請求預設值為 3。i 表示回應能否被增量處理;存在 i 時,伺服器可以把同 urgency 的頻寬分給多個資源,讓它們都更早開始,但每個資源完成可能更晚。沒有 i 時,更適合按順序傳送不可增量消費的物件。
GET /style.css HTTP/1.1
Host: example.test
Priority: u=1
GET /hero.jpg HTTP/1.1
Host: example.test
Priority: u=4, i伺服器回應也可以提供優先級提示給下游中間層;缺少回應標頭表示伺服器沒有改變客戶端優先級。未知參數應被忽略,不能把客戶端提供的值當成權限或計費依據。
3. 按協定版本選擇排程邊界
HTTP/1.1 沒有內建的多路複用優先級,伺服器主要受連線內順序、並發連線數和佇列影響。HTTP/2 與 HTTP/3 在一條多路複用連線上共享頻寬,排程器可以按 urgency 與 incremental 選擇下一段資料。HTTP/2、HTTP/3 還能透過對應的 PRIORITY_UPDATE 機制改變已送出請求的偏好,但實作不保證立即或嚴格執行。
4. 處理快取與代理
快取命中可能直接回傳,不經過來源站的業務排程;需要把優先級影響限制在傳輸和快取填充階段,不能讓普通 Priority 標頭改變物件授權或快取鍵。代理可以合併客戶端連線、建立不同後端連線或重寫回應優先級,因此應在每個邊界記錄原始值、最終值與選擇原因。快取規則仍由 Cache-Control、Vary 等欄位決定。
5. 處理重傳與公平性
QUIC 和 TCP 都會重傳遺失資料。高 urgency 的新資料不一定應該壓過低 urgency 的重傳,因為重傳可能解除已開始回應的阻塞;RFC 9218 把這個取捨交給傳輸實作與應用策略。跨連線競爭時,單連線的 u=0 不能保證取得全域最高頻寬。排程器應設定每連線配額、老化時間和最大連續傳送量,避免背景請求永久飢餓。
6. 防止優先級濫用與錯誤傳播
客戶端可以把所有請求標成 u=0,因此伺服器要按資源白名單、認證主體、頁面階段和歷史行為校正。可以限制最高 urgency、按租戶配額、對未知資源回到預設值,並記錄覆寫事件。跨代理傳遞時保留語意而非盲目複製字串;若下游不理解訊號,應安全忽略而不改變回應正確性。
7. 灰度、回退與驗收
先選擇固定頁面和低風險 CDN 節點,對一部分連線啟用伺服器改寫。比較同一網路、裝置、快取狀態和資源集合下的對照組,記錄 LCP、關鍵 CSS 完成時間、字型阻塞時長、背景 p95/p99、首位元組時間、重複下載、連線利用率和低優先級最長等待。任何體驗改善都要和錯誤率、頻寬成本及跨租戶公平一起判斷;若排程器異常,立即恢復預設優先級。
高品質示範回答
我會先定義首屏完成和背景請求的目標,再把資源分成 HTML、阻塞 CSS、字型、可增量媒體與背景資料。客戶端 Priority 只作為提示:我會按資源白名單、頁面階段、快取狀態和租戶配額校正,預設使用 urgency 3,關鍵資源降低數值,背景請求提高數值;只有能邊到邊消費的回應才使用 incremental。
HTTP/1.1 主要靠連線和佇列順序;HTTP/2、HTTP/3 由多路複用排程器按優先級傳送,並按需使用重新排序 frame。快取命中不應改變授權和快取鍵,代理要記錄原始與最終優先級。重傳不能盲目讓位給新資料,我會設定連線配額、老化和最大連續傳送量避免飢餓。灰度對比 LCP、關鍵資源完成、背景尾延遲、頻寬和低優先級等待;指標惡化就關閉伺服器改寫。
常見錯誤
- 把
Priority: u=0當作必須先完成的 SLA → 伺服器仍要考慮壅塞、快取和重傳 → 把它作為排程輸入並定義可觀測目標。 - 把
incremental當成「更快完成」 → 並行分片會讓單一物件完成更晚 → 只給可增量消費且有使用者收益的回應使用。 - 讓客戶端優先級改變快取鍵或授權 → 造成快取碎片或安全越權 → 保持快取與權限契約獨立。
- 只分析一條 HTTP/2 連線 → 跨連線競爭可能反轉結果 → 按連線、節點、網路和租戶切片驗證。
- 讓高優先級重傳永遠壓過其他資料 → 新回應或低優先級流可能永久等待 → 加入重傳策略、配額和老化。
- 只看 LCP → 背景尾延遲和頻寬成本可能惡化 → 同時設定使用者、可靠性、公平性和成本門檻。
追問及應對
所有客戶端都送出 u=0 怎麼辦?
把值視為不可信提示,按資源類型、頁面階段、認證主體和租戶配額重算;未知或異常請求回到預設值,並記錄覆寫原因。
incremental 是否總能改善體驗?
不能。它讓同 urgency 的回應共享頻寬,可能讓多個物件更早開始,卻讓每個物件更晚完成。只在消費者能處理部分資料且首位元組收益重要時啟用。
快取命中還需要 Priority 嗎?
命中通常繞過來源站業務佇列,但代理仍可能在連線上排程傳輸。Priority 不能進入授權邏輯或無理由改變快取鍵;應分別觀測命中、填充和傳送階段。
丟包時應先送重傳還是高 urgency 新資料?
沒有脫離上下文的答案。重傳可能解除已開始回應的阻塞,高 urgency 新資料可能更影響使用者;應結合流依賴、應用增量能力、壅塞狀態和可複算的體驗目標決定。
HTTP/1.1 能實現相同優先級嗎?
沒有 HTTP/2 那種多路複用優先級樹。可以在伺服器佇列、連線並發和資源排序上近似實現,但必須把它當實作策略,並驗證隊頭阻塞和連線競爭。
如何證明沒有低優先級飢餓?
記錄每個請求的排隊和首次傳送時間,按資源、連線和租戶計算最大等待及 p99;在壓力測試中持續注入高 urgency 流,確認老化、配額或截止時間能讓低優先級流獲得服務。