1. 程式人生 > >http請求響應全過程

http請求響應全過程

-a 平衡器 continue load 組織 要求 性能 attr domain

HTTP 無狀態性

HTTP 協議是無狀態的(stateless)。也就是說,同一個客戶端第二次訪問同一個服務器上的頁面時,服務器無法知道這個客戶端曾經訪問過,服務器也無法分辨不同的客戶端。HTTP 的無狀態特性簡化了服務器的設計,使服務器更容易支持大量並發的HTTP 請求。

HTTP 持久連接

HTTP1.0 使用的是非持久連接,主要缺點是客戶端必須為每一個待請求的對象建立並維護一個新的連接,即每請求一個文檔就要有兩倍RTT 的開銷。因為同一個頁面可能存在多個對象,所以非持久連接可能使一個頁面的下載變得十分緩慢,而且這種短連接增加了網絡傳輸的負擔。HTTP1.1 使用持久連接keepalive,所謂持久連接,就是服務器在發送響應後仍然在一段時間內保持這條連接,允許在同一個連接中存在多次數據請求和響應,即在持久連接情況下,服務器在發送完響應後並不關閉TCP 連接,而客戶端可以通過這個連接繼續請求其他對象。

HTTP/1.1 協議的持久連接有兩種方式:

非流水線方式:客戶在收到前一個響應後才能發出下一個請求;

流水線方式:客戶在收到 HTTP 的響應報文之前就能接著發送新的請求報文;

1、首先,在瀏覽器裏輸入網址:

技術分享圖片

2、瀏覽器根據域名解析IP地址:

技術分享圖片

瀏覽器根據訪問的域名找到其IP地址。DNS查找過程如下:
1)瀏覽器緩存:瀏覽器會緩存DNS記錄一段時間。 但操作系統沒有告訴瀏覽器儲存DNS記錄的時間,這樣不同瀏覽器會儲存個自固定的一個時間(2分鐘到30分鐘不等)。
2)系統緩存:如果在瀏覽器緩存裏沒有找到需要的域名,瀏覽器會做一個系統調用(windows裏是gethostbyname),這樣便可獲得系統緩存中的記錄。
3)路由器緩存:如果系統緩存也沒找到需要的域名,則會向路由器發送查詢請求,它一般會有自己的DNS緩存。
4)ISP DNS緩存:如果依然沒找到需要的域名,則最後要查的就是ISP緩存DNS的服務器。在這裏一般都能找到相應的緩存記錄。

域名解析原理:

1>一個域中的每個主機名與其IP地址的映射關系由這個域的DNS服務器負責管理,例如,"www.it.org”、“ftp.it.org”、“blog.it.org”等主機名都由管理域“it.org”的DNS服務器進行管理,而不能由管理域“org”的DNS服務器進行管理。

2>每個管理域都必須在其直接父域的DNS服務器上註冊該子域的名稱和該子域的DNS服務器的IP地址,例如,必須在管理域“org”的DNS服務器註冊子域“it.org”和其DNS服務器的IP地址後,域名“it.org”才能真正被外界所認可。

3>為了方便對頂級域名的統一管理,在頂級域名之上其實還有一個根域名,根域名用點(.)表示,例如,“www.it.org”也可以寫為“www.it.org.”,“www.it.org.”中的最後的那個點(.)就表示根域名。 Internet中的根域名由InterNIC(國際互聯網絡信息中心)集中管理,頂級域名和其下的域名則由擁有該域名的組織、公司和個人自己管理。

域名解析的方式主要有兩種,分別是:

技術分享圖片

或者

技術分享圖片

DNS有一個弊端,一個域名看上去只是對應一個單獨的IP地址。還好有幾種方法可以消除這個瓶頸:

1>循環 DNS 是DNS查找時返回多個IP時的解決方案。舉例來說,facebook.com實際上就對應了四個IP地址。

2>負載平衡器是以一個特定IP地址進行偵聽並將網絡請求轉發到集群服務器上的硬件設備。 一些大型的站點一般都會使用這種昂貴的高性能負載平衡器。

3>地理 DNS 根據用戶所處的地理位置,通過把域名映射到多個不同的IP地址提高可擴展性。這樣不同的服務器不能夠更新同步狀態,但映射靜態內容的話非常好。

4>Anycast 是一個IP地址映射多個物理主機的路由技術。 美中不足的是Anycast與TCP協議適應的不是很好,所以很少應用在那些方案中。大多數DNS服務器使用Anycast來獲得高效低延遲的DNS查找。

3、瀏覽器與web服務器建立一個TCP連接

4、瀏覽器給web服務器發送一個http請求:

技術分享圖片

一個http請求報文由請求行<request-line>、請求頭部<headers>、空行<blank-line>
和請求數據<request-body>4個部分組成,請求報文的一般格式如下圖:

技術分享圖片

1)請求行:由請求方法、URL和HTTP協議版本3個字段組成,它們用空格分隔。例如,GET /index.html HTTP/1.1。HTTP協議的請求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。而常見的有如下幾種:

1>GET:當客戶端要從服務器中讀取文檔時,當點擊網頁上的鏈接或者通過在瀏覽器的地址欄輸入網址來瀏覽網頁的,使用的都是GET方式。GET方法要求服務器將URL定位的資源放在響應報文的數據部分,回送給客戶端。使用GET方法時,請求參數和對應的值附加在URL後面,利用一個問號(“?”)代表URL的結尾與請求參數的開始,傳遞參數長度受限制。例如,/index.jsp?id=100&op=bind。通過GET方式傳遞的數據直接放在在地址中,所以GET方式的請求一般不包含”請求內容”部分,請求數據以地址的形式表現在請求行。地址中”?”之後的部分就是通過GET發送的請求數據,我們可以在地址欄中清楚的看到,各個數據之間用”&”符號隔開。顯然這種方式不適合傳送私密數據。另外,由於不同的瀏覽器對地址的字符限制也有所不同,一般最多只能識別1024個字符,所以如果需要傳送大量數據的時候,也不適合使用GET方式。如果數據是英文字母/數字,原樣發送,如果是空格,轉換為+,如果是中文/其他字符,則直接把字符串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX為該符號以16進制表示的ASCII。

2>POST:允許客戶端給服務器提供信息較多。POST方法將請求參數封裝在HTTP請求數據中,以名稱/值的形式出現,可以傳輸大量數據,這樣POST方式對傳送的數據大小沒有限制,而且也不會顯示在URL中。POST方式請求行中不包含數據字符串,這些數據保存在“請求內容”部分,各數據之間也是使用”&“符號隔開。POST方式大多用於頁面的表單中。因為POST也能完成GET的功能,因此多數人在設計表單的時候一律都使用POST方式,其實這是一個誤區。GET方式也有自己的特點和優勢,我們應該根據不同的情況來選擇是使用GET還是使用POST。

3>HEAD:就像GET,只不過服務端接受到HEAD請求後只返回響應頭,而不會發送響應內容。當我們只需要查看某個頁面的狀態的時候,使用HEAD是非常高效的,因為在傳輸的過程中省去了頁面內容。

2)請求頭部:由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號”:“分隔。請求頭部通知服務器有關於客戶端請求的信息,典型的請求頭有:

User-Agent:產生請求的瀏覽器類型。

Accept:客戶端可識別的內容類型列表。星號 “ * ” 用於按範圍將類型分組,用 “ */* ” 指示可接受全部類型,用“ type/* ”指示可接受 type 類型的所有子類型。

Host:要請求的主機名,允許多個域名同處一個IP地址,即虛擬主機。

Accept-Language:客戶端可接受的自然語言。

Accept-Encoding:客戶端可接受的編碼壓縮格式。

Accept-Charset:可接受的應答的字符集。

connection:連接方式(close 或 keepalive)。

Cookie:存儲於客戶端擴展字段,向同一域名的服務端發送屬於該域的cookie。

3)空行:最後一個請求頭部之後是一個空行,發送回車符和換行符,通知服務器以下不再有請求頭部。

4)請求數據:請求數據不在GET方法中使用,而在POST方法中使用。POST方法適用於需要客戶填寫表單的場合。與請求數據相關的最常使用的請求頭部是Content-Type和Content-Length。

請求報文示例:

  1. POST /search HTTP/1.1
  2. Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint,
  3. application/msword, application/x-silverlight, application/x-shockwave-flash, */*
  4. Referer: <a href="http://www.google.cn/">http://www.google.cn/</a>
  5. Accept-Language: zh-cn
  6. Accept-Encoding: gzip, deflate
  7. User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)
  8. Host: <a href="http://www.google.cn">www.google.cn</a>
  9. Connection: Keep-Alive
  10. Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g;
  11. NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-
  12. FxlRugatx63JLv7CWMD6UB_O_r
  13. hl=zh-CN&source=hp&q=domety

5、服務器的永久重定向響應:

技術分享圖片

服務器給瀏覽器響應一個301永久重定向響應,這樣瀏覽器就會訪問“http://www.facebook.com/” 而非“http://facebook.com/”。為什麽服務器一定要重定向而不是直接發送用戶想看的網頁內容呢?其中一個原因跟搜索引擎排名有關。如果一個頁面有兩個地址,就像http://www.igoro.com/和http://igoro.com/,搜索引擎會認為它們是兩個網站,結果造成每個搜索鏈接都減少從而降低排名。而搜索引擎知道301永久重定向是什麽意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網站排名下。還有就是用不同的地址會造成緩存友好性變差,當一個頁面有好幾個名字時,它可能會在緩存裏出現好幾次。

一個http響應報文由狀態行<status-line>、響應頭部<headers>、空行<blank-line>
和響應數據<response-body>4個部分組成,響應報文的一般格式如下圖:

技術分享圖片

1)狀態行: 由HTTP協議版本、服務器返回的響應狀態碼和響應狀態碼的文本描述組成。

狀態代碼由三位數字組成,第一個數字定義了響應的類別,且有五種可能取值。

1xx:信息性狀態碼,表示服務器已接收了客戶端請求,客戶端可繼續發送請求。

100 Continue

101 Switching Protocols

2xx:成功狀態碼,表示服務器已成功接收到請求並進行處理。

200 OK 表示客戶端請求成功

204 No Content 成功,但不返回任何實體的主體部分

206 Partial Content 成功執行了一個範圍(Range)請求

3xx:重定向狀態碼,表示服務器要求客戶端重定向。

301 Moved Permanently 永久性重定向,響應報文的Location首部應該有該資源的新URL

302 Found 臨時性重定向,響應報文的Location首部給出的URL用來臨時定位資源

303 See Other 請求的資源存在著另一個URI,客戶端應使用GET方法定向獲取請求的資源

304 Not Modified 客戶端發送附帶條件的請求(請求首部中包含如If-Modified-Since等指定首部)時,服務端有可能返回304,此時,響應報文中不包含任何報文主體。

307 Temporary Redirect 臨時重定向。與302 Found含義一樣。302禁止POST變換為GET,但實際使用時並不一定,307則更多瀏覽器可能會遵循這一標準,但也依賴於瀏覽器具體實現

4xx:客戶端錯誤狀態碼,表示客戶端的請求有非法內容。

400 Bad Request 表示客戶端請求有語法錯誤,不能被服務器所理解

401 Unauthonzed 表示請求未經授權,該狀態代碼必須與 WWW-Authenticate 報頭域一起使用

403 Forbidden 表示服務器收到請求,但是拒絕提供服務,通常會在響應正文中給出不提供服務的原因

404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL

5xx:服務器錯誤狀態碼,表示服務器未能正常處理客戶端的請求而出現意外錯誤。

500 Internel Server Error 表示服務器發生不可預期的錯誤,導致無法完成客戶端的請求

503 Service Unavailable 表示服務器當前不能夠處理客戶端的請求,在一段時間之後,服務器可能會恢復正常

2)響應頭部:由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號”:“分隔,典型的響應頭有:

Location:用於重定向接受者到一個新的位置。例如:客戶端所請求的頁面已不存在原先的位置,為了讓客戶端重定向到這個頁面新的位置,服務器端可以發回Location響應報頭後使用重定向語句,讓客戶端去訪問新的域名所對應的服務器上的資源

Server:包含了服務器用來處理請求的軟件信息及其版本。它和 User-Agent 請求報頭域是相對應的,前者發送服務器端軟件的信息,後者發送客戶端軟件(瀏覽器)和操作系統的信息

Vary:指示不可緩存的請求頭列表

Connection:連接方式

   對於請求來說:close(告訴 WEB 服務器或者代理服務器,在完成本次請求的響應後,斷開連接,不等待本次連接的後續請求了)。keepalive(告訴WEB服務器或者代理服務器,在完成本次請求的響應後,保持連接,等待本次連接的後續請求);

   對於響應來說:close(連接已經關閉); keepalive(連接保持著,在等待本次連接的後續請求); Keep-Alive:如果瀏覽器請求保持連接,則該頭部表明希望WEB 服務器保持連接多長時間(秒);例如:Keep-Alive:300;

   WWW-Authenticate:必須被包含在401 (未授權的)響應消息中,這個報頭域和前面講到的Authorization 請求報頭域是相關的,當客戶端收到 401 響應消息,就要決定是否請求服務器對其進行驗證。如果要求服務器對其進行驗證,就可以發送一個包含了Authorization 報頭域的請求

3)空行:最後一個響應頭部之後是一個空行,發送回車符和換行符,通知瀏覽器以下不再有響應頭部。

4)響應數據:服務器返回給客戶端的文本信息。

響應報文示例:

  1. HTTP/1.1 301 Moved Permanently
  2. Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,
  3. pre-check=0
  4. Expires: Sat, 01 Jan 2000 00:00:00 GMT
  5. Location: <a target=_blank href="http://www.facebook.com/">HTTP://www.facebook.com/</a>
  6. P3P: CP=”DSP LAW”
  7. Pragma: no-cache
  8. Set-Cookie: made_write_conn=deleted; expires=Thu, 12-Feb-2009 05:09:50 GMT;
  9. path=/; domain=.facebook.com; httponly
  10. Content-Type: text/html; charset=utf-8
  11. X-Cnection: close
  12. Date: Fri, 12 Feb 2010 05:09:51 GMT
  13. Content-Length: 0

6、瀏覽器跟蹤重定向地址:

技術分享圖片

現在瀏覽器知道了 “HTTP://www.facebook.com/”才是要訪問的正確地址,所以它會發送另一個http請求。

7、服務器“處理”請求:

服務器接收到獲取請求,然後處理並返回一個響應。這表面上看起來是一個順向的任務,但其實這中間發生了很多有意思的東西,就像作者博客這樣簡單的網站,何況像facebook那樣訪問量大的網站呢!web服務器軟件(像IIS和阿帕奇)接收到HTTP請求,然後確定執行某一請求處理來處理它。請求處理就是一個能夠讀懂請求並且能生成HTML來進行響應的程序(像ASP.NET,PHP,RUBY…)。

8、服務器發回一個HTML響應

9、釋放TCP連接

若connection 模式為close,則服務器主動關閉TCP 連接,客戶端被動關閉連接,釋放TCP 連接;若connection 模式為keepalive,則該連接會保持一段時間,在該時間內可以繼續接收請求;

10、客戶端瀏覽器解析HTML內容

客戶端將服務器響應的 html 文本解析並顯示

11、瀏覽器獲取嵌入在HTML中的對象

在瀏覽器顯示HTML時,它會註意到需要獲取其他地址內容的標簽。這時瀏覽器會發送一個獲取請求來重新獲得這些文件。這些地址都要經歷一個和HTML讀取類似的過程。所以瀏覽器會在DNS中查找這些域名,發送請求,重定向等等

http請求響應全過程