【譯者注:本文需要有一定的HTTP協議知識和瀏覽器解析頁面過程知識】
原文 :https://blog.golang.org/h2push
前言
HTTP/2被設計為解決HTTP/1.x的許多缺陷。當代網頁使用了許多資源:HTML、樣式表、腳本、圖片等等。在HTTP/1.x中這些資源每一個都必須明確地請求。這可能是一個很慢的過程。瀏覽器從獲取HTML開始,然后在它解析和評估頁面的時候,增量地獲取更多的資源。因為服務器必須等待瀏覽器做每一個請求,網絡經常是空閑的和未充分使用的。
為了改善延遲,HTTP/2引入了server push,它允許服務端推送資源給瀏覽器,在瀏覽器明確地請求之前。一個服務器經常知道一個頁面需要很多附加資源,在它響應瀏覽器第一個請求的時候,可以開始推送這些資源。這允許服務端去完全充分地利用一個可能空閑的網絡,改善頁面加載時間。
在協議層,HTTP/2 server push被push_promise 幀所驅動,一個PUSH_PROMISE描述了一個請求,即服務端預測瀏覽器將馬上要發出的請求。瀏覽器一收到PUSH_PROMISE,它馬上知道服務端將要傳輸這個資源。如果瀏覽器后續發現它需要這個資源,它會等待這個推送完成,而不是發送一個新的請求。這減少了瀏覽器花費在網絡等待上的時間 。
net/http包中的服務端推送
go1.8引入了來自http.Server對推送響應的支持。如果運行的server是一個HTTP/2的服務,并且進來的連接是使用HTTP/2的時候,這個特性是可用的。在任意一個HTTP handler中,你可以判斷http.ResponseWriter是否支持服務端推送,通過檢查它是否實現了新的http.Pusher接口。
例如,如果server知道app.js將要被請求來渲染頁面,如果http.Pusher可用,handler可以初始化一個push。
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if pusher, ok := w.(http.Pusher); ok {
// Push is supported.
if err := pusher.Push("/app.js", nil); err != nil {
log.Printf("Failed to push: %v", err)
}
}
// ...
})
因時間關系,今天晚上先譯到這……