HTTP協議是因特網的多媒體信使。HTTP能夠從遍及世界的Web服務器上將這些信息快迅速,便捷,可靠地搬移到人們桌面上的Web瀏覽器上去。git
HTTP協議主要分Web客戶端和服務器。其中Web服務器是Web資源的宿主。Web資源能夠包含任意媒體類型內容,HTTP協議爲了標識各類媒體類型,會給經過Web傳輸的對象都打上MIME類型的數據標籤格式。(MIME科普:最初設計MIME(Multipurpose Internet Mail Extension
,多用途因特網郵件擴展)是爲了解決在不一樣的電子郵件系統之間搬移報文時存在的問題。HTTP隨後也採用了它,用他來描述並標記多媒體內容。)github
同時,每一個web服務器資源都有一個名字去標識,這被稱爲統一資源標識符(Uniform Resource Identifier
)。URI有兩種類型,一種是咱們常見的統一資源定位符URL,另一種被稱爲統一資源名URN。後者仍處於試驗階段,未大範圍使用。web
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都有一樣的:"方案://服務器位置/路徑"結構。
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
幾乎沒有哪一個URL包含了全部這些組件。
URL最重要的3個部分是方案(scheme
),主機(host
)和路徑(path
)。
轉義表示法包含一個百分號%,後面跟着兩個表示字符ASCII碼的十六進制數。
例子http://www.baidu.com/%7Ejoe
~ 126(0x7E)
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鏈接,鏈接到可能運行在世界任何地方的服務器應用程序。
https://github.com:80/WilsonLiu95
瀏覽器利用解析出主機名 github.com
瀏覽器查詢這個主機名的IP地址 192.30.252.122
瀏覽器得到端口號 80
瀏覽器發起到192.30.252.122
端口80的鏈接
瀏覽器向服務器發送一條HTTP GET報文
瀏覽器從服務器讀取HTTP響應報文
瀏覽器關閉TCP鏈接
與創建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分組(一般是40-60字節)。這個分組中設置了一個特殊的SYN標記,說明這是一個鏈接請求。
若是服務器接收了鏈接,就會對一些鏈接參數進行計算,並向客戶端回送一個TCP分組,這個分組中的SYN和ACK標記都被置位了,說明鏈接請求已經被接收了。
最後,客戶端向服務器回送一條確認信息,通知它鏈接已成功創建。現代的TCP棧都容許客戶端在這個確認分組中發送數據。
若是鏈接只用來傳送少許的數據,這些交換過程就會嚴重下降HTTP的性能。小的HTTP事務可能會在TCP創建上花費50%或者更多的時間。
每一個TCP段都有一個序列號和數據完整性校驗和。每一個段的接收者收到無缺的段時,都會向發送者回送小的確認分組。若是發送者沒有在指定的窗口時間內收到確認信息,發送者就認爲分爲已被破壞或損毀,並重發數據。
爲了增長確認報文找到同向傳輸數據分組的可能性,不少TCP棧都實現了一種"延遲確認"算法。延遲確認算法會在一個特定的窗口時間(一般是100~200毫秒)內將輸出確認存放在緩衝區中,以尋找可以捎帶它的輸出數據分組。若是在那個時間段內沒有輸出數據分組,就講確認信息放在單獨的分組中傳送。
一般,延遲確認算法會引入至關大的時延,因此能夠調整或者禁止延遲確認算法。
TCP數據傳輸的性能還取決於TCP鏈接的使用期(age
)。TCP鏈接會隨着時間進行自我「調諧」,起初會限制鏈接的最大速度,若是數據成功傳輸,會隨着時間的推移提升傳輸的速度。這種調諧被稱爲TCP慢啓動(slow start
),用於防止因特網的忽然過載和擁塞。
Nagle算法鼓勵發送全尺寸(LAN上最大尺寸的分組大約是1500字節,在因特網上是幾百字節)的段。只有當全部其餘的分組都被確認以後,Nagle才容許發送非全尺寸的分組,若是其餘分仍然在傳輸過程當中,就將那部分數據緩存起來。只有當掛起分組被確認,或者緩存中積累了足夠發送一個全尺寸分組的數據時,纔會將緩存的數據發送出去。
Nagle算法會引起幾種HTTP性能問題。首先小的HTTP報文沒法填滿一個分組,可能會由於等待那些永遠不會到來的額外數據而產生時延。其次,Nagle算法與延時確認之間的交互存在問題——Nagle會阻止數據的發送,直到有確認分組抵達爲止,但確認分組自身會被延遲確認算法延遲100-200毫秒。
所以,HTTP應用程序經常會在本身的棧中設置參數TCP_NODELAY,禁用Nagle算法,提升性能。
當某個TCP端點關閉TCP鏈接時,會在內存中維護一個小的控制塊,用來記錄最近所關閉鏈接的IP地址和端口號。這類信息會維持一小段時間,以確保在這段時間內不會建立於相同地址和端口號的新鏈接。
客戶端每次鏈接到服務器上去時,都會得到一個新的端口號,以實現鏈接的惟一性。但因爲可用的源端口數量有限,所以會出現端口耗盡的狀況。就會沒法創建新的鏈接。
解決辦法:增長客戶端負載生成機器的數量,或者確保客戶端和服務器在循環使用幾個虛擬的IP地址以增長更多的鏈接組合。
HTTP容許在客戶端和最終的源端服務器之間存在一串HTTP中間實體(代理,高速緩存等)。能夠從客戶端開始,逐跳地將HTTP報文通過這些中間設備,轉發到源端服務器上去(或者進行反向傳輸)。
在某些狀況下,兩個相鄰的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的核心技術。但願你們可以喜歡。