http1.0/1.1/2.0/h2c/golang使用隨筆



一、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

 

以上內容,有網絡摘抄。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM