自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解開 HTTP/2 的面紗:HTTP/2 是如何建立連接的

網(wǎng)絡(luò) 通信技術(shù)
超文本傳輸協(xié)議(HTTP)是一種非常成功的協(xié)議。但是,HTTP/1.1 使用底層傳輸?shù)?方式,其中有幾個特性對今天的應(yīng)用程序性能有負(fù)面影響。

[[285457]]

前言

超文本傳輸協(xié)議(HTTP)是一種非常成功的協(xié)議。但是,HTTP/1.1 使用底層傳輸?shù)?方式,其中有幾個特性對今天的應(yīng)用程序性能有負(fù)面影響。

特別是,HTTP/1.0 在給定的 TCP 連接上一次只允許一個請求未完成。HTTP/1.1 添加了請求流水線操作(request pipelining),但這只是部分地解決了請求并發(fā)性,并且仍然受到隊(duì)首阻塞的影響。因此,需要發(fā)出許多請求的 HTTP/1.0 和 HTTP/1.1 客戶端使用多個連接到服務(wù)器以實(shí)現(xiàn)并發(fā),從而減少延遲。

[[285458]]

 

此外,HTTP 頭字段通常是重復(fù)且冗長的,導(dǎo)致不必要的網(wǎng)絡(luò)流量以及導(dǎo)致初始 TCP(https://tools.ietf.org/html/rfc7540#ref-TCP) 擁塞窗口被快速的填滿。當(dāng)在新的 TCP 連接上發(fā)出多個請求時,這可能導(dǎo)致過多的延遲。

HTTP/2 通過定義了一個優(yōu)化過的 HTTP 語義,它與底層連接映射,用這種方式來解決這些問題。具體而言,它允許在同一連接上交錯請求和響應(yīng)消息,并使用 HTTP 頭字段的有效編碼。它還允許對請求進(jìn)行優(yōu)先級排序,使更多重要請求更快地完成,從而進(jìn)一步提高性能。

HTTP/2 對網(wǎng)絡(luò)更友好,因?yàn)榕c HTTP/1.x 相比,可以使用更少的 TCP 連接。這意味著與其他流量和長連接的競爭減少,反過來可以更好地利用可用網(wǎng)絡(luò)容量。最后,HTTP/2 還可以通過使用二進(jìn)制消息幀來更有效地處理消息。

HTTP/2 最大限度的兼容 HTTP/1.1 原有行為:

1. 在應(yīng)用層上修改,基于并充分挖掘 TCP 協(xié)議性能。

2. 客戶端向服務(wù)端發(fā)送 request 請求的模型沒有變化。

3. scheme 沒有發(fā)生變化,沒有 http2://

4. 使用 HTTP/1.X 的客戶端和服務(wù)器可以無縫的通過代理方式轉(zhuǎn)接到 HTTP/2 上。

5. 不識別 HTTP/2 的代理服務(wù)器可以將請求降級到 HTTP/1.X。

一. HTTP/2 Protocol Overview

 

HTTP/2 為 HTTP 語義提供了優(yōu)化的傳輸。HTTP/2 支持 HTTP/1.1 的所有核心功能,但旨在通過多種方式提高效率。

HTTP/2 中的基本協(xié)議單元是一個幀。每種幀類型都有不同的用途。例如,HEADERS 和 DATA 幀構(gòu)成了 HTTP 請求和響應(yīng)的基礎(chǔ);其他幀類型(如 SETTINGS,WINDOW_UPDATE 和 PUSH_PROMISE)用于支持其他 HTTP/2 功能。

HTTP/2 是一個徹徹底底的二進(jìn)制協(xié)議,頭信息和數(shù)據(jù)包體都是二進(jìn)制的,統(tǒng)稱為“幀”。對比 HTTP/1.1 ,在 HTTP/1.1 中,頭信息是文本編碼(ASCII編碼),數(shù)據(jù)包體可以是二進(jìn)制也可以是文本。使用二進(jìn)制作為協(xié)議實(shí)現(xiàn)方式的好處,更加靈活。在 HTTP/2 中定義了 10 種不同類型的幀。

通過使每個 HTTP 請求/響應(yīng)交換與其自己的 stream 流相關(guān)聯(lián)來實(shí)現(xiàn)請求的多路復(fù)用。stream 流在很大程度上是彼此獨(dú)立的,因此阻塞或停止的請求或響應(yīng)不會阻止其他 stream 流的通信。

由于 HTTP/2 的數(shù)據(jù)包是亂序發(fā)送的,因此在同一個連接里會收到不同請求的 response。不同的數(shù)據(jù)包攜帶了不同的標(biāo)記,用來標(biāo)識它屬于哪個 response。

HTTP/2 把每個 request 和 response 的數(shù)據(jù)包稱為一個數(shù)據(jù)流(stream)。每個數(shù)據(jù)流都有自己全局唯一的編號。每個數(shù)據(jù)包在傳輸過程中都需要標(biāo)記它屬于哪個數(shù)據(jù)流 ID。規(guī)定,客戶端發(fā)出的數(shù)據(jù)流,ID 一律為奇數(shù),服務(wù)器發(fā)出的,ID 為偶數(shù)。

數(shù)據(jù)流在發(fā)送中的任意時刻,客戶端和服務(wù)器都可以發(fā)送信號(RST_STREAM 幀),取消這個數(shù)據(jù)流。HTTP/1.1 中想要取消數(shù)據(jù)流的唯一方法,就是關(guān)閉 TCP 連接。而 HTTP/2 可以取消某一次請求,同時保證 TCP 連接還打開著,可以被其他請求使用。

流量控制和優(yōu)先級確??梢杂行У厥褂枚嗦窂?fù)用流。流量控制有助于確保只傳輸接收者可以使用的數(shù)據(jù)。確定優(yōu)先級可確保首先將有限的資源定向到最重要的流。

HTTP/2 添加了一種新的交互模式,服務(wù)器可以將響應(yīng)推送到客戶端。服務(wù)器推送允許服務(wù)器推測性地將數(shù)據(jù)發(fā)送到服務(wù)器預(yù)測客戶端將需要這些數(shù)據(jù)的客戶端,通過犧牲一些網(wǎng)絡(luò)流量來抵消潛在的延遲。服務(wù)器通過合成請求來完成此操作,并將其作為 PUSH_PROMISE 幀發(fā)送。然后,服務(wù)器能夠在單獨(dú)的流上發(fā)送對合成請求的響應(yīng)。

由于連接中使用的 HTTP 頭字段可能包含大量冗余數(shù)據(jù),因此壓縮包含它們的幀。允許將許多請求壓縮成一個分組的做法對于通常情況下的請求大小具有特別有利的影響。

HTTP 協(xié)議不帶有狀態(tài),每次請求都必須附上所有信息。所以,請求的很多字段都是重復(fù)的,比如 Cookie 和 User Agent,每次請求即使是完全一樣的內(nèi)容,依舊必須每次都攜帶,這會浪費(fèi)很多帶寬,也影響速度。HTTP/1.1 雖然可以壓縮請求體,但是不能壓縮消息頭。有時候消息頭部很大。

HTTP/2 對這一點(diǎn)做了優(yōu)化,引入了頭信息壓縮機(jī)制(header compression)。一方面,頭信息使用 gzip 或 compress 壓縮后再發(fā)送;另一方面,客戶端和服務(wù)器同時維護(hù)一張頭信息表,所有字段都會存入這個表,生成一個索引號,以后就不發(fā)送同樣字段了,只發(fā)送索引號,這樣就提高速度了。

頭部壓縮大概可能有 95% 左右的提升,HTTP/1.1 統(tǒng)計(jì)的平均響應(yīng)頭大小有 500 個字節(jié)左右,而 HTTP/2 的平均響應(yīng)頭大小只有 20 多個字節(jié),提升比較大。

 

接下來分 4 部分詳細(xì)討論 HTTP/2。

解開 HTTP/2 的面紗:HTTP/2 是如何建立連接的

幀和流層描述了 HTTP/2 幀的結(jié)構(gòu)和形成多路復(fù)用流的方式。

幀和錯誤定義了包括 HTTP/2 中使用的幀和錯誤類型的詳細(xì)信息。

HTTP 映射和附加要求描述了如何使用幀和流表示 HTTP 語義。

雖然一些幀層和流層概念與 HTTP 隔離,但是該規(guī)范沒有定義完全通用的幀層。幀層和流層是根據(jù) HTTP 協(xié)議和服務(wù)器推送的需要而定制的。

二. Starting HTTP/2

HTTP/2 連接是在 TCP 連接之上運(yùn)行的應(yīng)用層協(xié)議??蛻舳耸?TCP 連接發(fā)起者。

HTTP/2 使用 HTTP/1.1 使用的相同 "http" 和 "https" URI scheme。HTTP/2 共享相同的默認(rèn)端口號: "http" URI 為 80,"https" URI 為 443。因此,需要處理對目標(biāo)資源 URI (例如 "http://example.org/foo" 或 "https://example.com/bar")的請求的實(shí)現(xiàn),首先需要發(fā)現(xiàn)上游服務(wù)器(客戶端希望建立連接的直接對等方)是否支持 HTTP/2。

1. HTTP/2 Version Identification

本文檔中定義的協(xié)議有兩個標(biāo)識符。

  • 字符串 "h2" 標(biāo)識 HTTP/2 使用傳輸層安全性(TLS)TLS12的協(xié)議。該標(biāo)識符用于 TLS 應(yīng)用層協(xié)議協(xié)商(ALPN)擴(kuò)展TLS-ALPN字段以及識別 HTTP/2 over TLS 的任何地方。

"h2�"字符串被序列化為 ALPN 協(xié)議標(biāo)識符,作為兩個八位字節(jié)序列:0x68,0x32。

  • 字符串 "h2c" 標(biāo)識通過明文 TCP 運(yùn)行 HTTP/2 的協(xié)議。此標(biāo)識符用于 HTTP/1.1 升級標(biāo)頭字段以及標(biāo)識 HTTP/2 over TCP 的任何位置。

"h2c" 字符串是從 ALPN 標(biāo)識符空間保留的,但描述了不使用 TLS 的協(xié)議。協(xié)商 "h2" 或 "h2c" 意味著使用本文檔中描述的傳輸,安全性,成幀和消息語義。

2. Starting HTTP/2 for "http" URIs

在沒有關(guān)于下一跳支持 HTTP/2 的 prior knowledge 的情況下請求 "http" URI 的客戶端使用 HTTP 升級機(jī)制([RFC7230]的第 6.7 節(jié))。客戶端通過發(fā)出包含帶有 "h2c" 標(biāo)記的 Upgrade 頭字段的HTTP/1.1 請求來完成此操作。這樣的 HTTP/1.1 請求必須包含一個 HTTP2-Settings(第 3.2.1 節(jié))頭字段。

例如:

GET / HTTP/1.1

Host: server.example.com

Connection: Upgrade, HTTP2-Settings

Upgrade: h2c

HTTP2-Settings:

在客戶端可以發(fā)送 HTTP/2 幀之前,必須完整地發(fā)送包含有效負(fù)載主體的請求。這意味著大型請求可以阻止連接的使用,直到完全發(fā)送為止。

如果初始請求與后續(xù)請求的并發(fā)性很重要,則可以使用 OPTIONS 請求執(zhí)行升級到 HTTP/2,但需要額外的往返。不支持 HTTP/2 的服務(wù)器可以響應(yīng)請求,就像沒有 Upgrade 頭字段一樣:

HTTP/1.1 200 OK

Content-Length: 243

Content-Type: text/html

...

服務(wù)器必須忽略 Upgrade 頭字段中的 "h2" 標(biāo)記。具有 "h2" 的令牌的存在意味著 HTTP/2 over TLS,這種方式替代 3.3 節(jié)中所述協(xié)商過程。

支持 HTTP/2 的服務(wù)器通過 101(交換協(xié)議)響應(yīng)接受升級。在響應(yīng) 101 末尾的空行之后,服務(wù)器可以開始發(fā)送 HTTP/2 幀。這些幀必須包括對啟動升級的請求的響應(yīng)。

例如:

HTTP/1.1 101 Switching Protocols

Connection: Upgrade

Upgrade: h2c

[ HTTP/2 connection ...

服務(wù)器發(fā)送的第一個 HTTP/2 幀必須是由 SETTINGS 幀組成的服務(wù)器連接前奏。收到 101 響應(yīng)后,客戶端必須發(fā)送連接前奏,其中包括 SETTINGS 幀。

在升級之前發(fā)送的 HTTP/1.1 請求被賦予 stream 流標(biāo)識符 1 (參見第 5.1.1 節(jié)),它是默認(rèn)優(yōu)先級值(第 5.3.5 節(jié))。Stream 流 1 從客戶端隱式"半封閉"的流向服務(wù)器(參見第5.1節(jié)),因?yàn)檎埱笫亲鳛?HTTP/1.1 請求完成的。在開始 HTTP/2 連接之后,stream 流 1 用于響應(yīng)。

3. HTTP2-Settings Header Field

從 HTTP/1.1 升級到 HTTP/2 的請求必須包含一個 "HTTP2-Settings" 頭字段。HTTP2-Settings 標(biāo)頭字段是一個特定于連接的 header 字段,其中包含管理 HTTP/2 連接的參數(shù),這個參數(shù)在服務(wù)器接受升級請求的情況下提供的。

  1. HTTP2-Settings = token68 

如果此 header 字段不存在或存在多個連接,則服務(wù)器不得升級到 HTTP/2 的連接。服務(wù)器不得發(fā)送此 header 字段。

HTTP2-Settings 頭字段的內(nèi)容是 SETTINGS 幀的有效負(fù)載,編碼為 base64url 字符串(即[RFC4648]第 5 節(jié)中描述的 URL 和文件名安全的 Base64 編碼,省略任何尾隨的 '=' 字符)。ABNF RFC5234(RFC5234:https://tools.ietf.org/html/rfc5234) 生成 "token68" 在 [RFC7235]的第 2.1 節(jié)中定義。

由于升級僅用于立即連接,因此發(fā)送 HTTP2-Settings header 字段的客戶端也必須在 Connection 頭字段中發(fā)送 "HTTP2-Settings" 作為連接選項(xiàng),以防止它被轉(zhuǎn)發(fā)。

服務(wù)器解碼并解釋這些值,就像任何其他 SETTINGS 幀一樣。不必明確確認(rèn)這些設(shè)置,因?yàn)?101 響應(yīng)用作隱式確認(rèn)。在升級請求中提供這些值,目的的為了使客戶端有機(jī)會在從服務(wù)器接收任何幀之前提供參數(shù)。

4. Starting HTTP/2 for "https" URIs

向 "https" URI發(fā)出請求的客戶端使用 TLS TLS12(https://tools.ietf.org/html/rfc7540#ref-TLS12) 和應(yīng)用層協(xié)議協(xié)商(ALPN)擴(kuò)展 TLS-ALPN(https://tools.ietf.org/html/rfc7540#ref-TLS-ALPN)。

HTTP/2 over TLS 使用 "h2" 協(xié)議標(biāo)識符。"h2c" 協(xié)議標(biāo)識符不得由客戶端發(fā)送或由服務(wù)器選擇; "h2c" 協(xié)議標(biāo)識符描述了一個不使用 TLS 的協(xié)議。

一旦 TLS 協(xié)商完成,客戶端和服務(wù)器都必須發(fā)送連接前奏。

5. Starting HTTP/2 with Prior Knowledge

客戶端可以通過其他方式了解特定服務(wù)器是否支持 HTTP/2。例如,ALT-SVC 描述了一種可以獲得服務(wù)器是否支持 HTTP/2 的機(jī)制。

客戶端必須發(fā)送連接前奏,然后可以立即將 HTTP/2 幀發(fā)送到服務(wù)器; 服務(wù)器可以通過連接前奏的存在來識別這些連接。這只影響通過明文 TCP 建立 HTTP/2 連接; 通過 TLS 支持 HTTP/2 的實(shí)現(xiàn)必須在 TLS TLS-ALPN 中使用協(xié)議協(xié)商。同樣,服務(wù)器必須發(fā)送連接前奏。

如果沒有其他信息,先前對 HTTP/2 的支持并不是一個強(qiáng)信號,即給定服務(wù)器將支持 HTTP/2 以用于將來的連接。例如,可以更改服務(wù)器配置,使群集服務(wù)器中的實(shí)例之間的配置不同,或者更改網(wǎng)絡(luò)條件。

6. HTTP/2 Connection Preface

"連接前奏" 有些地方也會翻譯成 "連接序言"。

在 HTTP/2 中,每個端點(diǎn)都需要發(fā)送連接前奏作為正在使用的協(xié)議的最終確認(rèn),并建立 HTTP/2 連接的初始設(shè)置??蛻舳撕头?wù)器各自發(fā)送不同的連接前奏。

客戶端連接前奏以 24 個八位字節(jié)的序列開始,以十六進(jìn)制表示法為:

  1. 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a 

也就是說,連接前奏以字符串 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" 開頭。該序列必須后跟 SETTINGS 幀,該幀可以為空??蛻舳嗽谑盏?101 (交換協(xié)議)響應(yīng)(指示成功升級)或作為 TLS 連接的第一個應(yīng)用程序數(shù)據(jù)八位字節(jié)后立即發(fā)送客戶端連接前奏。如果啟動具有服務(wù)器對協(xié)議支持的 prior knowledge 的 HTTP/2 連接,則在建立連接時發(fā)送客戶端連接前奏。

注意:選擇客戶端連接前奏,以便大部分 HTTP/1.1 或 HTTP/1.0 服務(wù)器和中間件不會嘗試處理更多幀。請注意,這并未解決 TALKING 中提出的問題。

連接前奏里面的字符串連起來是 PRISM ,這個單詞的意思是“棱鏡”,就是 2013 年斯諾登爆出的“棱鏡計(jì)劃”。

服務(wù)器連接前奏包含一個可能為空的 SETTINGS 幀,該幀必須是服務(wù)器在 HTTP/2 連接中發(fā)送的第一幀。

作為連接前奏的一部分從對等端收到的 SETTINGS 幀,必須在發(fā)送連接前奏后得到確認(rèn)。

為避免不必要的延遲,允許客戶端在發(fā)送客戶端連接前奏后立即向服務(wù)器發(fā)送其他幀,而無需等待接收服務(wù)器連接前奏。但是,需要注意的是,服務(wù)器連接前奏 SETTINGS 幀可能包含參數(shù),這些參數(shù)是客戶端希望與服務(wù)器通信時必須的參數(shù)。在接收到 SETTINGS 幀后,客戶端應(yīng)該遵守所建立的任何參數(shù)。在某些配置中,服務(wù)器可以在客戶端發(fā)送附加幀之前發(fā)送 SETTINGS,從而提供避免此問題的機(jī)會。

客戶端和服務(wù)器必須將無效的連接前奏視為 PROTOCOL_ERROR 類型的連接錯誤。在這種情況下可以省略 GOAWAY 幀,因?yàn)闊o效的連接前奏表明對等方?jīng)]有使用 HTTP/2。

最后,我們抓包看一下 HTTP/2 over TLS 是如何建立連接的。當(dāng) TLS 握手結(jié)束以后(TLS 握手的流程這里暫時省略,客戶端和服務(wù)端已經(jīng)通過 ALPN 協(xié)商出了接下來應(yīng)用層使用 HTTP/2 協(xié)議進(jìn)行通信,于是會見到類似如下的抓包圖:

 

可以看到在 TLS 1.3 Finished 消息之后,緊接著就是 HTTP/2 的連接序言,Magic 幀。

 

客戶端連接前奏以 24 個八位字節(jié)的序列開始,以十六進(jìn)制表示法為:

  1. 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a 

連接前奏就是字符串 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" 開頭。Magic 幀之后緊跟著 SETTINGS 幀。當(dāng)服務(wù)端成功 ack 了這條消息,并且沒有連接報錯,那么 HTTP/2 協(xié)議就算連接建立完成了。

 

責(zé)任編輯:武曉燕 來源: 碼個蛋
相關(guān)推薦

2019-07-02 08:24:07

HTTPHTTPSTCP

2023-09-06 12:01:50

HTTP協(xié)議信息

2019-11-17 22:47:53

HTTP23

2020-03-08 21:22:03

HTTP112

2024-11-05 08:16:04

HTTP/3HTTP 2.0QUIC

2019-09-23 08:35:52

2019-04-12 10:44:39

2021-10-30 19:57:00

HTTP2 HTTP

2018-11-14 15:00:08

HTTP程序員前端

2021-07-27 14:50:15

axiosHTTP前端

2021-07-23 15:55:31

HTTPETag前端

2021-05-26 05:18:51

HTTP ETag Entity Tag

2015-11-24 15:22:53

HTTP2 WEB 內(nèi)網(wǎng)穿透

2021-12-15 11:46:46

HTTP2Nginx

2019-04-15 14:37:23

HTTPTCP長連接

2019-01-14 15:31:42

HTTP23

2015-10-30 15:42:05

HTTP網(wǎng)絡(luò)協(xié)議

2016-10-21 10:36:54

http2spdynode.js

2015-11-10 09:25:05

HTTP2提升性能

2015-02-05 09:25:51

HTTPSSPDYHTTP2
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號