HTTP 們
HTTP
https://notfalse.net/39/http-message-format
HyperText Transfer Protocol
一種應用層的通訊協定
簡單來說就是應用程式之間的一種溝通規範,規定好大家資料格式長什麼樣子,互相該如何來回訊息。如果大家都依照這種統一規範來做自己的東西,那麼在銜接上就會很容易
http 通常使用 tcp 協定 (http3 是 udp)
建立 tcp 連線 3 way handshake
基於 tcp 的 http 們,一開始要過三次的訊息交換來建立連線
詳細請參考 https://notfalse.net/7/three-way-handshake
注意這時傳送的訊息跟應用程式實際溝通時的 request 和 response 不一樣
note: ack 回應時不單是seq+1,而是 seq+(整個header+data的長度)
Stateless
每個 request 都不會預設 server 知道自己之前做過什麼
Request 要依靠自己提供完整的資訊,或提供線索讓 server 知道去哪裡找到資訊 (在 header 帶著 cookie 之類的)
Request, Response
Request 長相如下 (Ref: https://documentation.help/DogeTool-HTTP-Requests-vt/http_request.htm)
Response
各代 http
不同代的 http 都有一些問題,下面簡單舉幾個例子
HTTP/1.0
預設不使用 keep-alive (然後好像大家真的都沒用XD)
這樣的話每次request都要建立一個TCP連線,想法是為了避免 client 佔著 server 太久,所以做完一件事情就關掉
如果開一個網頁要讀取很多東西 -> 建立很多連線(3 way) -> 耗費資源
HTTP/1.1
預設持久連線,重複使用同一個TCP連線
要馬上關閉的話要特別在 header 裡面的 Connection 寫
有 head of line blocking 的問題
http1.1 有 pipeline 功能嘗試解決這個問題
但似乎規定 server 需要依照收到 request 的順序回給 client,代表每個 req 都要多帶一些資訊,且應用程式都必須特別處理這一部分,複雜度太高,且很多 proxy 根本不是你能控制的,所以都沒人在用。
HOLB 還是存在
比起 1.0 還多了一些 header etag 之類的東西
cache: https://blog.techbridge.cc/2017/06/17/cache-introduction/
可以對 body 的部分進行編碼順便壓縮,常見的像是 gzip
https://crypto.stackexchange.com/questions/40215/encoding-vs-compression-vs-encryption
HTTP/2.0
也是基於 tcp,http2 許多東西都與 http1.1相容,像是 methods、status code 那些
然後優化了其他東西
主要有下面幾個變動
-
可以 server push (主動丟東西給 client),在之前的 http 中,都需要 client 先發 request 後 server 才可回應
-
header 壓縮 (hpack),可以壓縮到剩下幾 byte,原本的可能數十甚至數百
-
上面提過的 holb 問題解決了(解決了應用層的,但 tcp 本身網路層就有 holb,http3 才會試著用 udp 來解決),一條 tcp 連線裡面可以有多個 stream
例如一個 request 會有一個 stream id x,request 可以被拆成 frame 們,到目的地再組起來,不同 request 的一堆 frame 們都可以不照順序傳輸。
其實長得還滿像 tcp packet 的 XD -
Binary protocol
這條不得不說從字面上看起來真的很看不懂XDD
後來查到這篇 https://stackoverflow.com/questions/58498116/why-is-it-said-that-http2-is-a-binary-protocol 才比較了解一點
大意就是,原本基於文字的 http,接收的人看到資料就是一串 character,需要一個個字去讀出來解析,找到 newline character 之類的,速度超慢。
且在傳輸上,一個 request 或是 response 都必須一次傳送到達目的地,在這之前其他人都不能用這條連線(與第三點相關)。
而 http2 的每個 frame 都很有結構(https://tools.ietf.org/html/rfc7540#section-4.1),譬如前面 n 個 bit 代表 frame 長度,接下來 m 個 bit 代表什麼什麼,內容多長等等的,都可以預先知道,在解析上就可以非常容易
http3.0
tcp 接收資料時會確保資料封包是連續的,才會依照順序把資料拿給應用程式
譬如有 1 2 3 4 5個封包
如果傳送中 1 3 正確到達但 2 掉了,tcp 就只能等到 2 到達後才把 3 也一起拿來用(即使 1 3 這兩個封包在應用層上都可以直接使用,但 tcp 並不瞭解應用層的事情)
且在此同時 sliding window 也可能被卡住,傳送端或線路上即使空閒也不會繼續傳送後面的封包,造成 holb 的問題
http3 就用 udp + QUIC 來解決這個問題
QUIC 也是一種傳輸層的協議,提供可靠傳輸
至於細節還沒研究 XD
現在還沒有被很廣泛的使用
下一篇可能會拿 websocket 和 http2 比較看看,因為現在其實很多瀏覽器都支援 http2 了,http2 又有 server push 的功能,感覺和 websocket 還滿像的 ?? GRPC???