概述HTTP
HTTP協議是因特網的多媒體信使。HTTP可以從遍佈世界的Web伺服器上將這些資訊快迅速,便捷,可靠地搬移到人們桌面上的Web瀏覽器上去。
HTTP協議主要分Web客戶端和伺服器。其中Web伺服器是Web資源的宿主。Web資源可以包含任意媒體型別內容,HTTP協議為了標識各種媒體型別,會給通過Web傳輸的物件都打上MIME型別的資料標籤格式。(MIME科普:最初設計MIME(Multipurpose Internet Mail Extension
,多用途因特網郵件擴充套件)是為了解決在不同的電子郵件系統之間搬移報文時存在的問題。HTTP隨後也採用了它,用他來描述並標記多媒體內容。)
同時,每個web伺服器資源都有一個名字去標識,這被稱為統一資源識別符號(Uniform Resource Identifier
)。URI有兩種型別,一種是我們常見的統一資源定位符URL,另外一種被稱為統一資源名URN。後者仍處於試驗階段,未大範圍使用。
web頁面可以包含多個物件,如一個頁面會包括許多圖片,視訊,音訊等內容。客戶端通過向Web伺服器傳送請求命令來進行事務處理。伺服器響應客戶端請求,並傳送相應資料。
請求和響應報文都有固定的規範。報文由一行一行簡單字串組成的。HTTP報文都是純文字,而不是二進位制程式碼,所以人們可以很方便的進行讀寫(但難以解析)。報文分為三部分
起始行
GET /index.html HTTP/1.0
首部欄位 每個首部欄位包含一個名字和一個值,為了便於解析,兩者之間用冒號來分割。首部以一個空行結束。
主體 起始行和首部都是文字形式且都是結構化的,主體則可以包含任意的二進位制資料,當然也可以包含文字。
HTTP協議的報文是通過傳輸控制協議(Transmission Control Protocol,TCP
)連線從一個地方搬移到另外一個地方去的。
TCP提供了
無差錯的資料傳輸
按序傳輸 (資料總是會按照傳送的順序到達)
未分段的資料流 (可以在任意時刻以任意尺寸將資料傳送出去)
在HTTP客戶端向伺服器傳送報文之前,需要用網際協議(Internet Protocol,IP
)地址和埠號在客戶端和伺服器之間建立一條TCP/IP連線。首先需要將URL進行DNS解析成IP地址,再用IP地址連線Web伺服器,預設埠是80。
除了客戶端與伺服器之外,還有許多比較重要的Web結構元件
代理 位於客戶端和伺服器之間的HTTP中間實體
快取 HTTP的倉庫,使常用頁面的副本可以儲存在離客戶端更近的地方
閘道器 連線其他應用程式的特殊Web伺服器
隧道 對HTTP通訊報文進行盲轉發的特殊代理
Agent代理 發起自動HTTP請求的半智慧Web客戶端
URL與資源
URL提供了一種統一的資源命名方式,大多數URL都有同樣的:"方案://伺服器位置/路徑"結構。
URL的語法
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
幾乎沒有哪個URL包含了所有這些元件。
URL最重要的3個部分是方案(scheme
),主機(host
)和路徑(path
)。
URL編碼
轉義表示法包含一個百分號%,後面跟著兩個表示字元ASCII碼的十六進位制數。
例子http://www.baidu.com/%7Ejoe
~ 126(0x7E)
HTTP報文
HTTP報文是在HTTP應用程式之間發生的資料塊。這些資料塊以一些文字形式的元資訊(meta-information
)開頭,這些資訊描述了報文的內容及含義,後面跟著可選的資料部分。這些報文在客戶端,伺服器和代理之間流動。
報文的語法
所有的報文都可以分為兩類:請求報文(request message
)和響應報文(response message
)。
請求報文
<method> <request-URL> <version>
<headers>
<entity-body>
響應報文
<version> <status> <reason-phrase>
<headers>
<entity-body>
起始行
方法
方法 | 描述 |
---|---|
GET | 從伺服器獲取一份文件 |
HEAD | 只從伺服器獲取文件的首部 |
POST | 向伺服器傳送需要處理的資料 |
PUT | 將請求的主體部分儲存在伺服器上 |
PUT | 對可能經過代理伺服器傳送到伺服器上去的報文進行追蹤 |
OPTIONS | 決定可以在伺服器上執行哪些方法 |
DELETE | 從伺服器上刪除一份文件 |
並不是所有伺服器都實現了上述7種方法,而且,由於HTTP設計的易於擴充套件,所以其他伺服器可能還會實現一些自己的請求方法。
狀態碼
整體範圍 | 已定義範圍 | 分類 |
---|---|---|
100 ~ 199 | 100~101 | 資訊提示 |
200~299 | 200~206 | 成功 |
300~399 | 300~305 | 重定向 |
400~499 | 400~415 | 客戶端錯誤 |
500~599 | 500~505 | 伺服器錯誤 |
當前的HTTP版本只為每類狀態定義了幾個程式碼,隨著協議的發展,HTTP規範中會正式的定義更多的狀態碼,如果收到了不認識的狀態碼,可能是有人將其作為當前協議的擴充套件定義的。可以根據其所處範圍,將它作為那個類別中一個普通的成員來處理。
首部
首部分類:
通用首部 既可以出現在請求報文中又可以出現在響應報文中
請求首部 提供更多有關請求的資訊
響應首部 提供更多有關響應的資訊
實體首部 描述主體的長度和內容,或者資源自身
擴充套件首部 規範中沒有定義的新首部
實體的主體部分
HTTP報文的第三部分是可選的實體主體部分。實體的主體是HTTP報文的負荷,就是HTTP要傳輸的內容。
連線管理
世界上幾乎所有的HTTP通訊都是由TCP/IP承載的,TCP/IP是全球計算機及網路裝置都在使用的一種常用的分組交換網路分層協議集。客戶端應用程式可以開啟一條TCP/IP連線,連線到可能執行在世界任何地方的伺服器應用程式。
web瀏覽器通過TCP連線與web伺服器進行互動的流程
https://github.com:80/WilsonLiu95
瀏覽器利用解析出主機名
github.com
瀏覽器查詢這個主機名的IP地址
192.30.252.122
瀏覽器獲得埠號
80
瀏覽器發起到
192.30.252.122
埠80的連線瀏覽器向伺服器傳送一條HTTP GET報文
瀏覽器從伺服器讀取HTTP響應報文
瀏覽器關閉TCP連線
HTTP事務的時延
與建立TCP連線,以及傳輸請求和響應報文的時間相比,事務處理時間可能是很短的。除非客戶端或伺服器超載,或正在處理複雜的動態資源,否則HTTP時延就是由TCP網路時延構成的。
HTTP事務時延的有以下幾種主要原因
客戶端首先需要根據URI確定Web伺服器的IP地址和埠號。其中IP地址需要通過DNS解析URL中的主機名獲得,這可能花費數十秒的時間。
客戶端向伺服器傳送TCP連線請求,即著名的"三次握手"。這個值通常最多隻有一兩秒鐘,但如果有數百個HTTP事務的話,這個值就會快速疊加上去。
因特網傳輸報文,以及伺服器處理請求報文都需要花費時間。
web伺服器回送HTTP響應也需要時間。
這些TCP網路時延取決於硬體速度,網路和伺服器的負載,請求和響應報文的尺寸,以及客戶端和伺服器之間的距離。TCP協議的技術複雜性也會對時延產生巨大的影響。
效能聚焦區域
一下是其餘一些會對HTTP產生影響,最常見的相關時延
TCP連線建立握手
TCP慢啟動擁塞控制
資料聚焦的Nagle演算法
用於捎帶確認的TCP延遲確認演算法
TIME_WAIT時延和埠耗盡
TCP連線建立握手
TCP連線握手需要經過一下幾個步驟
酷虎的向伺服器傳送一個小的TCP分組(通常是40-60位元組)。這個分組中設定了一個特殊的SYN標記,說明這是一個連線請求。
如果伺服器接收了連線,就會對一些連線引數進行計算,並向客戶端回送一個TCP分組,這個分組中的SYN和ACK標記都被置位了,說明連線請求已經被接收了。
最後,客戶端向伺服器回送一條確認資訊,通知它連線已成功建立。現代的TCP棧都允許客戶端在這個確認分組中傳送資料。
如果連線只用來傳送少量的資料,這些交換過程就會嚴重降低HTTP的效能。小的HTTP事務可能會在TCP建立上花費50%或者更多的時間。
延遲確認
每個TCP段都有一個序列號和資料完整性校驗和。每個段的接收者收到完好的段時,都會向傳送者回送小的確認分組。如果傳送者沒有在指定的視窗時間內收到確認資訊,傳送者就認為分為已被破壞或損毀,並重發資料。
為了增加確認報文找到同向傳輸資料分組的可能性,很多TCP棧都實現了一種"延遲確認"演算法。延遲確認演算法會在一個特定的視窗時間(通常是100~200毫秒)內將輸出確認存放在緩衝區中,以尋找能夠捎帶它的輸出資料分組。如果在那個時間段內沒有輸出資料分組,就講確認資訊放在單獨的分組中傳送。
通常,延遲確認演算法會引入相當大的時延,所以可以調整或者禁止延遲確認演算法。
TCP慢啟動
TCP資料傳輸的效能還取決於TCP連線的使用期(age
)。TCP連線會隨著時間進行自我“調諧”,起初會限制連線的最大速度,如果資料成功傳輸,會隨著時間的推移提高傳輸的速度。這種調諧被稱為TCP慢啟動(slow start
),用於防止因特網的突然過載和擁塞。
Nagle演算法與TCP_NODELAY
Nagle演算法鼓勵傳送全尺寸(LAN上最大尺寸的分組大約是1500位元組,在因特網上是幾百位元組)的段。只有當所有其他的分組都被確認之後,Nagle才允許傳送非全尺寸的分組,如果其他分仍然在傳輸過程中,就將那部分資料快取起來。只有當掛起分組被確認,或者快取中積累了足夠傳送一個全尺寸分組的資料時,才會將快取的資料傳送出去。
Nagle演算法會引發幾種HTTP效能問題。首先小的HTTP報文無法填滿一個分組,可能會因為等待那些永遠不會到來的額外資料而產生時延。其次,Nagle演算法與延時確認之間的互動存在問題——Nagle會阻止資料的傳送,直到有確認分組抵達為止,但確認分組自身會被延遲確認演算法延遲100-200毫秒。
因此,HTTP應用程式常常會在自己的棧中設定引數TCP_NODELAY,禁用Nagle演算法,提高效能。
TIME_WAIT累計和埠耗盡
當某個TCP端點關閉TCP連線時,會在記憶體中維護一個小的控制塊,用來記錄最近所關閉連線的IP地址和埠號。這類資訊會維持一小段時間,以確保在這段時間內不會建立於相同地址和埠號的新連線。
客戶端每次連線到伺服器上去時,都會獲得一個新的埠號,以實現連線的唯一性。但由於可用的源埠數量有限,因此會出現埠耗盡的情況。就會無法建立新的連線。
解決辦法:增加客戶端負載生成機器的數量,或者確保客戶端和伺服器在迴圈使用幾個虛擬的IP地址以增加更多的連線組合。
HTTP連線的處理
HTTP允許在客戶端和最終的源端伺服器之間存在一串HTTP中間實體(代理,快取記憶體等)。可以從客戶端開始,逐跳地將HTTP報文經過這些中間裝置,轉發到源端伺服器上去(或者進行反向傳輸)。
Connection首部
在某些情況下,兩個相鄰的HTTP應用程式會為它們共享的連線應用一組選項。HTTP的Connection首部欄位中有一個由逗號分隔的連線標籤列表,這些標籤為此連線指定了一些不會傳播到其他連線中去的選項。
Connection首部可以承載3種不同型別的標籤
HTTP首部欄位名,列出了只與此連線有關的首部
任意標籤值,用於描述此連線的非標準選項
值close,說明操作完成之後需關閉這條持久連線
序列事務處理時延
如果支隊連線進行簡單的管理,TCP的效能時延可能會疊加起來。序列載入的另外一個缺點是,有些瀏覽器在物件載入完畢之前無法獲知物件的尺寸,而且它們可能需要尺寸資訊來決定將物件放在螢幕的什麼位置上,所以在載入了足夠多的物件之前,無法在螢幕上顯示任何內容。
以下為4種提高HTTP連線效能的技術。
並行連線 通過多條TCP連線發起併發的HTTP請求
持久連線 重用TCP連線,以消除連線及關閉時延
管道化連線 通過共享的TCP連線發起併發的HTTP請求
複用的連線 交替傳送請求和響應報文 (實驗階段)
並行連線
HTTP允許客戶端開啟多條連線,並行地執行多個HTTP事務。
並行連線可以提高符合頁面的傳輸速度,但並行連線也有一些缺點:
每個事務都會開啟/關閉一條新的連線,好耗費時間和頻寬
由於TCP慢啟動特性的存在,每條新連線的效能會有所降低
可開啟的並行連線數量實際上是有限的
持久連線
Web客戶端經常會開啟到同一個站點的連線。因此,初始化了對某伺服器的HTTP請求的應用程式很可能會在不久的將來對那臺伺服器發起更多的請求。這種性質被稱為站點區域性性。
因此,HTTP/1.1允許HTTP裝置在事務處理結束之後將TCP連線保持在開啟狀態,以便為將來的HTTP請求重用現存的連線。
在事務處理結束之後仍然保持在開啟狀態的TCP連線被稱為持久連線。非持久連線會在每個事務結束之後關閉。持久連線會在不同事務之間保持開啟狀態,直到客戶端或伺服器決定將其關閉為止。
重用已對目標伺服器開啟的空閒持久連線,就可以避開緩慢的連線建立階段。而且,已經開啟的連線還可以避免慢啟動的擁塞適應階段,以便更快速地進行資料的傳輸。
持久連線有一些比並行連線更好的地方。持久連線降低了時延和連線建立的開銷,將連線保持在已調諧狀態,而且減少了開啟連線的潛在數量。(持久連線有兩種型別:比較老的HTTP/1.0+ "keep-alive"連線,以及現代的HTTP/1.1 "persistent"連線)
並行連線與持久連線配合使用可能是最高效的方式。
管道化連線
允許在持久連線上可選的使用請求管道,這是相對於keep-alive
連線的又一效能優化。
在響應到達之前,可以將多條請求放入佇列。當第一條請求通過網路流向地球另一端的伺服器時,第二條和第三條請求也可以開始傳送了。在高時延網路條件下,這樣做可以降低網路的環回時間。
總結
本文為《http權威指南》的第一部分,由第一到四章組成,介紹了HTTP的基礎構件和HTTP的核心技術。希望大家能夠喜歡。