一、http基本概念
1.1 http是網絡的上層應用層,由請求和響應組成,是一個標准的客戶端服務器模型,且是無狀態的協議。
1.2 http默認端口是80,承載於tls和ssl之上,通過加密、認證方式保證數據傳輸的安全,稱為https,https默認端口443.
1.3 早期http傳輸html,現在應用廣泛,常見於各種接口、數據傳輸
1.4 http通常基於tcp的,具體傳輸關系和過程,可自行看此類專題。
1.5 影響http網絡請求的主要因素:帶寬和延遲
瀏覽器阻塞(HOL blocking)、
DNS 查詢(DNS Lookup)、尋IP地址過程耗時,可用DNS緩存減少頻繁lookup
建立連接(Initial connection)。TCP三次握手在高延遲的場景下影響較明顯,慢啟動則對文件類大請求影響較大。
二、http1和http1.1區別
2.1長鏈接
HTTP1.1支持長連接,在一個TCP連接上可以傳送多個HTTP請求和響應,減少了建立和關閉連接的消耗和延遲,在HTTP1.1中默認開啟長連接keep-alive,一定程度上彌補了HTTP1.0每次請求 都要創建連接的缺點。HTTP1.0需要使用keep-alive參數來告知服務器端要建立一個長連接。
(見http header request Connection)
2.2帶寬優化及網絡連接的使用
HTTP1.0中存在一些浪費帶寬的現象,例如客戶端只是需要某個對象的一部分,而服務器卻將整個對象送過來了,並且不支持斷點續傳功能。HTTP1.1支持只發送header信息(不帶任何body信息),如果服務器認為客戶端有權限請求服務器,則返回100,客戶端接收到100才開始把請求body發送到服務器;如果返回401,客戶端就可以不用發送請求body了節約了帶寬。
(RFC2616標准http1.1,支持OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE和CONNECT方法、content-range accept-range。感興趣可深入研究)
2.3HOST頭處理
在HTTP1.0中認為每台服務器都綁定一個唯一的IP地址,因此,請求消息中的URL並沒有傳遞主機名(hostname),HTTP1.0沒有host域。隨着虛擬主機技術的發展,在一台物理服務器上可以存在多個虛擬主機(Multi-homed Web Servers),並且它們共享一個IP地址。HTTP1.1的請求消息和響應消息都支持host域,且請求消息中如果沒有host域會報告一個錯誤(400 Bad Request)。
(見http header request host)
2.4緩存處理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires來做為緩存判斷的標准,HTTP1.1則引入了更多的緩存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供選擇的緩存頭來控制緩存策略。
(見http header response cache-control/Expires)
2.5錯誤通知的管理
在HTTP1.1中新增了24個錯誤狀態響應碼,如409(Conflict)表示請求的資源與資源的當前狀態發生沖突;410(Gone)表示服務器上的某個資源被永久性的刪除。(具體百度)
三、http1.1和http2區別
3.1新的二進制格式(Binary Format)
HTTP1.x的解析是基於文本。基於文本協議的格式解析存在天然缺陷,文本的表現形式有多樣性,要做到健壯性考慮的場景必然很多,二進制則不同,只認0和1的組合。基於這種考慮HTTP2.0的協議解析決定采用二進制格式,實現方便且健壯。
3.1多路復用
即連接共享,即每一個request都是是用作連接共享機制的。一個request對應一個id,這樣一個連接上可以有多個request,每個連接的request可以隨機的混雜在一起,接收方可以根據request的 id將request再歸屬到各自不同的服務端請求里面。HTTP1.1也可以多建立幾個TCP連接,來支持處理更多並發的請求,但是創建TCP連接本身也是有開銷的。
3.2header壓縮
在HTTP1.1中,HTTP請求和響應都是由狀態行、請求/響應頭部、消息主體三部分組成。一般而言,body體都會經過gzip壓縮,或者本身傳輸的就是壓縮過后的二進制文件,但狀態行和頭部卻沒有經過任何壓縮,直接以純文本傳輸。隨着Web功能越來越復雜,每個頁面產生的請求數也越來越多,導致消耗在頭部的流量越來越多,尤其是每次都要傳輸UserAgent、Cookie這類不會頻繁變動的內容,完全是一種浪費。
HTTP1.1不支持header數據的壓縮,HTTP2.0使用HPACK算法對header的數據進行壓縮,這樣數據體積小了,在網絡上傳輸就會更快。
3.3服務端推送
https://www.cnblogs.com/wetest/p/8040202.html
四、常見疑問
4.1HTTP2.0的多路復用和HTTP1.X中的長連接復用有什么區別?
HTTP/1.* 一次請求-響應,建立一個連接,用完關閉;每一個請求都要建立一個連接;
HTTP/1.1 Pipeling解決方式為,若干個請求排隊串行化單線程處理,后面的請求等待前面請求的返回才能獲得執行機會,一旦有某請求超時等,后續請求只能被阻塞,毫無辦法,也就是人們常說的線頭阻塞;
HTTP/2多個請求可同時在一個連接上並行執行。某個請求任務耗時嚴重,不會影響到其它連接的正常執行
4.2服務器推送到底是什么?
服務端推送能把客戶端所需要的資源伴隨着index.html一起發送到客戶端,省去了客戶端重復請求的步驟。正因為沒有發起請求,建立連接等操作,所以靜態資源通過服務端推送的方式可以極大地提升速度
https://www.cnblogs.com/wetest/p/8040202.html
4.3h2和h2c
h2指的是建立在 TLS 之上的 HTTP/2 協議,即 HTTP/2 Over TLS。
h2c指的是建立在 TCP 之上的 HTTP/2 協議, 即 HTTP/2 Over TCP,HTTP/2 without TLS。
對於后端接口性質的http2.0,非瀏覽器請求行為,可使用h2c,減少tls握手/驗證的開銷。可在可靠的內網中直接通信
五、golang對於http2.0的支持
Go 在 1.6的時候已經支持 HTTP/2 了, 1.8 開始支持 PUSH 功能
h2c 這個功能的討論2016年就開始了( issue#14141 ),最終5月份的這個功能加上了,這樣你就可以在沒有TLS使用http/2高性能的特性了。
h2:
var srv http.Server //http2.VerboseLogs = true srv.Addr = ":8972" http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello http2")) }) http2.ConfigureServer(&srv, &http2.Server{}) go func() { log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key")) }()
h2c:
mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello h2c") }) s := &http.Server{ Addr: ":8972", Handler: mux, } http2.ConfigureServer(s, &http2.Server{}) log.Fatal(s.ListenAndServe())
現在默認是HTTP/1.1、准備內網開啟http2.0,golang knownRoundTripperImpl方法會默認檢測使用http1.1或http2.0
以上內容,有網絡摘抄。