TCP/IP、HTTP、HTTPS、HTTP2.0
TCP/IP、HTTP、HTTPS、HTTP2.0
HTTP,全稱超文本傳輸協議(HTTP,HyperText Transfer Protocol),是一個客戶端和服務器端請求和應答的標準(TCP),互聯網上應用最為廣泛的一種網絡協議。客戶端是終端用戶,服務器端是網站。通過使用Web瀏覽器、網絡爬蟲或者其它的工具,客戶端發起一個到服務器上指定端口(默認端口為80)的HTTP請求。
HTTPS,即加密後的HTTP。HTTP協議傳輸的數據都是未加密的,也就是明文的,因此使用HTTP協議傳輸隱私信息非常不安全。HTTPS都是用的TLS協議,但是由於SSL出現的時間比較早,並且依舊被現在瀏覽器所支持,因此SSL依然是HTTPS的代名詞,但無論是TLS還是SSL都是上個世紀的事情,SSL最後一個版本是3.0,今後TLS將會繼承SSL優良血統繼續為我們進行加密服務。目前TLS的版本是1.2,定義在RFC 5246中,暫時還沒有被廣泛的使用。
HTTP2.0,下一代的HTTP協議。相比於HTTP1.x,大幅度的提升了web性能,進一步減少了網絡延時和擁塞。
各自的RFC相關文檔自己去搜吧,https://www.rfc-editor.org/。
一、TCP/IP
為了了解HTTP,有必要先理解一下TCP/IP。目前,存在兩種劃分模型的方法,OSI七層模型和TCP/IP模型,具體的區別不在闡述。HTTP是建立在TCP協議之上,所以HTTP協議的瓶頸及其優化技巧都是基於TCP協議本身的特性,例如tcp建立連接的3次握手和斷開連接的4次揮手以及每次建立連接帶來的RTT延遲時間。
TCP三次握手四次揮手的原理,由於篇幅關系,具體請看TCP協議的三次握手和四次揮手,
二、HTTP
超文本傳輸協議(HyperText Transfer Protocol) 是伴隨著計算機網絡和瀏覽器而誕生,在瀏覽器出現之前,人們是怎麽使用網絡的?,不管怎麽說,那個時代對於現在的我們,有點難以想象。。。之後,網景發布了Netscape Navigator瀏覽器,才慢慢打開了互聯網的幕布。如果根據OSI來劃分的話,HTML屬於表示層,而HTTP屬於應用層。HTTP發展至今,經過了HTTP0.9、HTTP1.0、HTTP1.1、HTTP2.0的時代,雖然2.0很久之前就正式提出標準,大多瀏覽器也支持了,但是網絡支持HTTP2.0的卻很少。
2.1 HTTP報文分析
報文,是網絡中交換和傳輸的基本單元,即一次性發送的數據塊。HTTP的報文是由一行一行組成的,純文本,而且是明文,即:如果能監聽你的網絡,那麽你發送的所有賬號密碼都是可以看見的,為了保障數據隱秘性,HTTPS隨之而生。
2.1.1 請求報文:
為了形象點,我們把報文標準和實際的結合起來看。
下面是實際報文,以訪問自己的網站(http://www.wenzhihuai.com)中的一個鏈接為例。
請求行
請求行由方法字段、URL 字段 和HTTP 協議版本字段 3 個部分組成,他們之間使用空格隔開。常用的 HTTP 請求方法有 GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT,這裏我們使用的是GET方法,訪問的是/biaoqianyun.do,協議使用的是HTTP/1.1。
GET:當客戶端要從服務器中讀取某個資源時,使用GET 方法。如果需要加傳參數的話,需要在URL之後加個"?",然後把參數名字和值用=連接起來,傳遞參數長度受限制,通常IE8的為4076,Chrome的為7675。例如,/index.jsp?id=100&op=bind。
POST:當客戶端給服務器提供信息較多時可以使用POST 方法,POST 方法向服務器提交數據,比如完成表單數據的提交,將數據提交給服務器處理。GET 一般用於獲取/查詢資源信息,POST 會附帶用戶數據,一般用於更新資源信息。POST 方法將請求參數封裝在HTTP 請求數據中,以名稱/值的形式出現,可以傳輸大量數據;
請求頭部
請求頭部由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號“:”分隔。請求頭部通知服務器有關於客戶端請求的信息,典型的請求頭有:
User-Agent:產生請求的瀏覽器類型;
Accept:客戶端可識別的響應內容類型列表;星號 “ * ” 用於按範圍將類型分組,用 “ / ” 指示可接受全部類型,用“ type/* ”指示可接受 type 類型的所有子類型;
Accept-Language:客戶端可接受的自然語言;
Accept-Encoding:客戶端可接受的編碼壓縮格式;
Accept-Charset:可接受的應答的字符集;
Host:請求的主機名,允許多個域名同處一個IP 地址,即虛擬主機;
connection:連接方式(close 或 keepalive),如果是close的話就需要進行TCP四次揮手關閉連接,如果是keepalive,表明還能繼續使用,這是HTTP1.1對1.0的新增,加快了網絡傳輸,默認是keepalive;
Cookie:存儲於客戶端擴展字段,向同一域名的服務端發送屬於該域的cookie;
空行
最後一個請求頭之後是一個空行,發送回車符和換行符,通知服務器以下不再有請求頭;
請求包體
請求包體不在 GET 方法中使用,而是在POST 方法中使用。POST 方法適用於需要客戶填寫表單的場合。與請求包體相關的最常使用的是包體類型 Content-Type 和包體長度 Content-Length;
2.1.2 響應報文
同樣,先粘貼報文標準。
抓包,以訪問(http://www.wenzhihuai.com)為例。
狀態行
狀態行由 HTTP 協議版本字段、狀態碼和狀態碼的描述文本 3 個部分組成,他們之間使用空格隔開,描述文本一般不顯示;
狀態碼:由三位數字組成,第一位數字表示響應的類型,常用的狀態碼有五大類如下所示:
1xx:服務器已接收,但客戶端可能仍要繼續發送;
2xx:成功;
3xx:重定向;
4xx:請求非法,或者請求不可達;
5xx:服務器內部錯誤;
響應頭部:響應頭可能包括:
Location:Location響應報頭域用於重定向接受者到一個新的位置。例如:客戶端所請求的頁面已不存在原先的位置,為了讓客戶端重定向到這個頁面新的位置,服務器端可以發回Location響應報頭後使用重定向語句,讓客戶端去訪問新的域名所對應的服務器上的資源;
Server:Server 響應報頭域包含了服務器用來處理請求的軟件信息及其版本。它和 User-Agent 請求報頭域是相對應的,前者發送服務器端軟件的信息,後者發送客戶端軟件(瀏覽器)和操作系統的信息。
Vary:指示不可緩存的請求頭列表;
Connection:連接方式,這個跟rquest的類似。
空行:最後一個響應頭部之後是一個空行,發送回車符和換行符,通知服務器以下不再有響應頭部。
響應包體:服務器返回給客戶端的文本信息;
2.2 HTTP特性
HTTP的主要特點主要能概括如下:
2.2.1 無狀態性
即,當客戶端訪問完一次服務器再次訪問的時候,服務器是無法知道這個客戶端之前是否已經訪問過了。優點是不需要先前的信息,能夠更快的應答,缺點是每次連接傳送的數據量增大。這種做法不利於信息的交互,隨後,Cookie和Session就應運而生,至於它倆有什麽區別,可以看看COOKIE和SESSION有什麽區別?。
2.2.2 持久連接
HTTP1.1 使用持久連接keepalive,所謂持久連接,就是服務器在發送響應後仍然在一段時間內保持這條連接,允許在同一個連接中存在多次數據請求和響應,即在持久連接情況下,服務器在發送完響應後並不關閉TCP連接,客戶端可以通過這個連接繼續請求其他對象。
2.2.3 其他
支持客戶/服務器模式、簡單快速(請求方法簡單Get和POST)、靈活(數據對象任意)
2.3 影響HTTP的因素
影響HTTP請求的因素:
- 帶寬
好像只要上網這個因素是一直都有的。。。即使再快的網絡,也會有偶爾網絡慢的時候。。。 - 延遲
(1) 瀏覽器阻塞
一個瀏覽器對於同一個域名,同時只能有4個鏈接(根據不同瀏覽器),如果超了後面的會被阻塞。
常用瀏覽器阻塞數量看下圖。
(2) DNS查詢
瀏覽器建立連接是需要知道服務器的IP的,DNS用來將域名解析為IP地址,這個可以通過刷新DNS緩存來加快速度。
(3) 建立連接
由之前第一章的就可以看出,HTTP是基於TCP協議的,即使網絡、瀏覽器再快也要進行TCP的三次握手,在高延遲的場景下影響比較明顯,慢啟動則對文件請求影響較大。
2.4 缺陷
- 耗時:傳輸數據每次都要建立連接;
- 不安全:HTTP是明文傳輸的,只要在路由器或者交換機上截取,所有東西(賬號密碼)都是可見的;
- Header內容過大:通常,客戶端的請求header變化較小,但是每次都要攜帶大量的header信息,導致傳輸成本增大;
- keepalive壓力過大:持久連接雖然有一點的優點,但同時也會給服務器造成大量的性能壓力,特別是傳輸圖片的時候。
BTW:明文傳輸有多危險,可以去試試,下面是某個政府網站,采用wireshark抓包,身份證、電話號碼、住址什麽的全暴露出來,所以,,,只要在路由器做點小動作,你的信息是全部能拿得到的,畢竟政府。
由於涉及的隱私太多,打了馬賽克
三、HTTPS
由於HTTP報文的不安全性,網景在1994年就創建了HTTPS,並用在瀏覽器中。最初HTTPS是和SSL一起使用,然後演化為TLS。SSL/TLS在OSI模型中都是表示層的協議。SSL使 用40 位關鍵字作為RC4流加密算法,這對於商業信息的加密是合適的。
3.1 SSL/TLS
SSL(Secure Sockets Layer),簡稱安全套接入層,最初由上世紀90年代由網景公司設計。開啟 SSL 會增加內存、CPU、網絡帶寬的開銷,後二者跟你使用的 cipher suite 密切相關,其中參數很多,很難一概而論。開啟 SSL 的前提是你的 cert 和 key 必須放在 TCP endpoint,你是否信得過那臺設備。
TLS(Transport Layer Security),簡稱安全傳輸層協議,該協議由兩層組成: TLS 記錄協議(TLS Record)和 TLS 握手協議(TLS Handshake)。較低的層為 TLS 記錄協議,位於某個可靠的傳輸協議(例如 TCP)上面,與具體的應用無關,所以,一般把TLS協議歸為傳輸層安全協議。
由於本人在加密算法上面知識匱乏,就不誤人子弟了,有興趣可以看看百度百科裏的資料,SSL,TLS
3.2 SPDY
2012年google提出了SPDY的方案,大家才開始從正面看待和解決老版本HTTP協議本身的問題,SPDY可以說是綜合了HTTPS和HTTP兩者有點於一體的傳輸協議,主要解決:
降低延遲,針對HTTP高延遲的問題,SPDY優雅的采取了多路復用(multiplexing)。多路復用通過多個請求stream共享一個tcp連接的方式,解決了HOL blocking的問題,降低了延遲同時提高了帶寬的利用率。
請求優先級(request prioritization)。多路復用帶來一個新的問題是,在連接共享的基礎之上有可能會導致關鍵請求被阻塞。SPDY允許給每個request設置優先級,這樣重要的請求就會優先得到響應。比如瀏覽器加載首頁,首頁的html內容應該優先展示,之後才是各種靜態資源文件,腳本文件等加載,這樣可以保證用戶能第一時間看到網頁內容。
header壓縮。前面提到HTTP1.x的header很多時候都是重復多余的。選擇合適的壓縮算法可以減小包的大小和數量。
基於HTTPS的加密協議傳輸,大大提高了傳輸數據的可靠性。
服務端推送(server push),采用了SPDY的網頁,例如我的網頁有一個sytle.css的請求,在客戶端收到sytle.css數據的同時,服務端會將sytle.js的文件推送給客戶端,當客戶端再次嘗試獲取sytle.js時就可以直接從緩存中獲取到,不用再發請求了。SPDY構成圖。
3.3 HTTPS報文分析
跟之前的報文分析一樣,我們使用wireshark來抓包分析,以在百度上搜索點東西為例。
192.168.1.103為本地電腦的ip地址,14.215.177.39為百度服務器地址。下面是步驟:
- 客戶端通過發送 Client Hello 報文開始 SSL 通信。報文中包含客戶端支持的 SSL 的指定版本、加密組件(Cipher Suite)列表(所使用的加密算法及密鑰長度等)。
- 服務器可進行 SSL 通信時,會以 Server Hello 報文作為應答。和客戶端一樣,在報文中包含 SSL 版本以及加密組件。服務器的加密組件內容是從接收到的客戶端加密組件內篩選出來的。之後服務器發送 Certificate 報文。報文中包含公開密鑰證書。最後服務器發送 Server Hello Done 報文通知客戶端,最初階段的SSL握手協商部分結束。
- SSL 第一次握手結束之後,客戶端以 Client Key Exchange 報文作為回應。接著客戶端繼續發送 Change Cipher Spec 報文。該報文會提示服務器,在此報文之後的通信會采用 Pre-master secret 密鑰加密。客戶端發送 Finished 報文。該報文包含連接至今全部報文的整體校驗值。
- 服務器同樣發送 Change Cipher Spec 報文。 服務器同樣發送 Finished 報文。
- 服務器和客戶端的 Finished 報文交換完畢之後,SSL 連接就算建立完成。當然,通信會受到 SSL 的保護。從此處開始進行應用層協議的通信,即發送 HTTP請求。 應用層協議通信,即發送 HTTP 響應。
當然,用一張圖更容易解釋
簡單地說就是下面。
當我們追蹤流的數據的時候,可以看到,基本上都是亂碼,經過加密,數據是看不到,如果需要在wireshark上看到,則需要在wireshark中配置ssl。
3.4 HTTPS全站化
現今,感覺只要和商業利益有關的,就不得不涉及到加密這類東西。淘寶、京東、唯品會這些電商可謂是最早推行全站https的,這類電商是離用戶金錢最近的企業。截止今年底,基本所有商業網站也基本實現了HTTPS。。。。至於小站點,比如個人網站,玩玩還是可以的。如果一個網站需要由HTTP全部變為HTTPS,那麽需要關註下面幾點:
- CA證書,大部分證書都是需要收費的,當然,自己在服務器上用openssl也可以,不過瀏覽器會提示當前私密連接不安全這個警告,普通人看到這種信息是不會繼續瀏覽的,所以,想使用HTTPS,可以使用Let‘s Encrypt,由谷歌等公司推行。
- HTTPS性能優化,SSL握手,HTTPS 對速度會有一定程度的降低,但是只要經過合理優化和部署,HTTPS 對速度的影響完全可以接受。
- CPU計算壓力,HTTPS中大量的秘鑰算法計算,對CPU的壓力可想而知。
至於我自己的個人網站,之前實現了https,用的免費證書,但是由於HTTPS下的網站,所有子鏈都要使用HTTPS,使用了七牛雲的CDN,如果要使用HTTPS加速,是要收費的,所以只能放棄。。。
四、HTTP2.0
HTTP2.0,相較於HTTP1.x,大幅度的提升了web性能。在與HTTP/1.1完全語義兼容的基礎上,進一步減少了網絡延遲和傳輸的安全性。HTTP2.0可以說是SPDY的升級版(基於SPDY設計的),但是依然存在一些不同點:HTTP2.0支持明文傳輸,而SPDY強制使用HTTPS;HTTP2.0消息頭的壓縮算法采用HPACK,而非SPDY采用的DEFLATE。
4.1 歷史
HTTP 2.0在2013年8月進行首次合作共事性測試。在開放互聯網上HTTP 2.0將只用於https://網址,而 http://網址將繼續使用HTTP/1,目的是在開放互聯網上增加使用加密技術,以提供強有力的保護去遏制主動攻擊。HTTP 2.0是在SPDY(An experimental protocol for a faster web, The Chromium Projects)基礎上形成的下一代互聯網通信協議。HTTP/2 的目的是通過支持請求與響應的多路復用來較少延遲,通過壓縮HTTPS首部字段將協議開銷降低,同時增加請求優先級和服務器端推送的支持。
4.2 HTTP2.0新特性
相較於HTTP1.1,HTTP2.0的主要優點有采用二進制幀封裝,傳輸變成多路復用,流量控制算法優化,服務器端推送,首部壓縮,優先級等特點。
4.2.1 二進制幀
HTTP1.x的解析是基於文本的,基於文本協議的格式解析存在天然缺陷,文本的表現形式有多樣性,要做到健壯性考慮的場景必然很多。而HTTP/2會將所有傳輸的信息分割為更小的消息和幀,然後采用二進制的格式進行編碼,HTTP1.x的頭部信息會被封裝到HEADER frame,而相應的Request Body則封裝到DATA frame裏面。不改動HTTP的語義,使用二進制編碼,實現方便且健壯。
4.2.2 多路復用
所有的請求都是通過一個 TCP 連接並發完成。HTTP/1.x 雖然通過 pipeline 也能並發請求,但是多個請求之間的響應會被阻塞的,所以 pipeline 至今也沒有被普及應用,而 HTTP/2 做到了真正的並發請求。同時,流還支持優先級和流量控制。當流並發時,就會涉及到流的優先級和依賴。即:HTTP2.0對於同一域名下所有請求都是基於流的,不管對於同一域名訪問多少文件,也只建立一路連接。優先級高的流會被優先發送。圖片請求的優先級要低於 CSS 和 SCRIPT,這個設計可以確保重要的東西可以被優先加載完。
4.2.3 流量控制
TCP協議通過sliding window的算法來做流量控制。發送方有個sending window,接收方有receive window。http2.0的flow control是類似receive window的做法,數據的接收方通過告知對方自己的flow window大小表明自己還能接收多少數據。只有Data類型的frame才有flow control的功能。對於flow control,如果接收方在flow window為零的情況下依然更多的frame,則會返回block類型的frame,這張場景一般表明http2.0的部署出了問題。
4.2.4 服務器端推送
服務器端的推送,就是服務器可以對一個客戶端請求發送多個響應。除了對最初請求的響應外,服務器還可以額外向客戶端推送資源,而無需客戶端明確地請求。當瀏覽器請求一個html,服務器其實大概知道你是接下來要請求資源了,而不需要等待瀏覽器得到html後解析頁面再發送資源請求。
4.2.5 首部壓縮
HTTP 2.0 在客戶端和服務器端使用“首部表”來跟蹤和存儲之前發送的鍵-值對,對於相同的數據,不再通過每次請求和響應發送;通信期間幾乎不會改變的通用鍵-值對(用戶代理、可接受的媒體類型,等等)只 需發送一次。事實上,如果請求中不包含首部(例如對同一資源的輪詢請求),那麽 首部開銷就是零字節。此時所有首部都自動使用之前請求發送的首部。
如果首部發生變化了,那麽只需要發送變化了數據在Headers幀裏面,新增或修改的首部幀會被追加到“首部表”。首部表在 HTTP 2.0 的連接存續期內始終存在,由客戶端和服務器共同漸進地更新 。本質上,當然是為了減少請求啦,通過多個js或css合並成一個文件,多張小圖片拼合成Sprite圖,可以讓多個HTTP請求減少為一個,減少額外的協議開銷,而提升性能。當然,一個HTTP的請求的body太大也是不合理的,有個度。文件的合並也會犧牲模塊化和緩存粒度,可以把“穩定”的代碼or 小圖 合並為一個文件or一張Sprite,讓其充分地緩存起來,從而區分開叠代快的文件。
4.3 HTTP1.1與HTTP2.0的對比
以訪問https://http2.akamai.com/demo為例。
4.4 報文
訪問https://http2.akamai.com/demo,谷歌瀏覽器的報文沒有顯示出協議,此處使用火狐瀏覽器。
響應頭部分如下。
請求頭如下。
采用淘寶網站為例,淘寶目前采用主站使用HTTP1.1,資源使用HTTP2.0,少些使用SPDY協議。目前也是業界比較流行的做法。
參考
- HTTPS那些事
- 如何搭建一個HTTP2.0的網站
- HTTP/2.0 相比1.0有哪些重大改進?
- HTTP2.0 demo
- Http、Https、Http2前身
- HTTP報文
- HTTP、HTTP2.0、SPDY、HTTPS 你應該知道的一些事
- HTTPS權威指南
- HTTP2.0的奇妙日常
- curl 支持 HTTP2
- 淘寶HTTPS探索
- HTTPS完全協議詳解
歡迎訪問我的個人網站。http://www.wenzhihuai.com
TCP/IP、HTTP、HTTPS、HTTP2.0