做爲一名軟件開發或是網絡技術人員,你應該對Web應用程序的運行原理和協議交換,以及涉及到的技術:如瀏覽器、HTTP、HTML、Web服務器和請求處理程序等都有所瞭解才行。在這篇文章中,咱們將深刻探討你訪問某個URL時發生的一系列事情。php
一、你在瀏覽器中輸入某個URLhtml
咱們從這裏開始:ajax
圖 1數據庫
二、瀏覽器查找該域名對應的IP地址編程
圖 2瀏覽器
第一步是找出所訪問域名對應的IP地址,按如下順序循環查找DNS記錄:緩存
◆瀏覽器緩存 - 瀏覽器會緩存DNS記錄一段時間,有趣的是,操做系統不會告訴瀏覽器每條DNS記錄的存活時間,瀏覽器按照固定的週期進行緩存(每種瀏覽器的保留時間從2-30分鐘長度不定)。安全
◆操做系統緩存 - 若是瀏覽器緩存中沒有要找的記錄,瀏覽器會產生一個系統調用(在Windows中是gethostbyname),操做系統有它本身的緩存。服務器
◆路由器緩存 - 請求繼續來到你的路由器,路由器一般也有本身的DNS緩存。cookie
◆ISP DNS緩存 - 下一步要檢查的是ISP的DNS服務器,固然也是有緩存的。
◆遞歸查找 - ISP的DNS服務器開始一個遞歸查找,從根域服務器開始,到.com頂級域名服務器,再到Facebook的域名服務器,正常狀況下,DNS服務器將會緩存.com域名服務器的名字,所以不必定須要訪問根域服務器。
下面是一個遞歸DNS查找過程示意圖:
圖 3
關於DNS一個使人擔憂的問題是,整個域名如wikipedia.org或facebook.com只映射到單個IP地址,幸運的是,有許多方法來消除這個問題。
◆循環DNS :DNS查找返回多個IP地址,例如,facebook.com真實狀況是映射到了4個IP地址。
◆負載均衡: 由專用硬件監聽一個特定IP地址,而後將請求轉發給其它服務器,大型網站通常都使用了昂貴的高性能負載均衡設備。
◆基於地理位置的DNS: 將域名映射到不一樣地理位置的IP地址提升擴展性,對於託管靜態內容的服務器佈局來講,這個方法頗有用,不一樣服務器之間不須要相互同步狀態。
◆Anycast(任播): 它是一種路由技術,單個IP地址能夠映射到多臺物理服務器,遺憾的是,任播對TCP不友好,在實際中不多使用。
大多數DNS服務器自己使用任播實現高可用和DNS查找的低延遲。
三、瀏覽器向Web服務器發送一個HTTP請求
圖 4
Facebook的主頁是不會直接從瀏覽器緩存提取的,由於動態頁面要麼很快(或當即)過時,所以瀏覽器將向Facebook服務器發送一條請求:
GET http://facebook.com/ HTTP/1.1 Accept: application/x-ms-application, image/jpeg, application/xaml+xml, [...] User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...] Accept-Encoding: gzip, deflate Connection: Keep-Alive Host: facebook.com Cookie: datr=1265876274-[...]; locale=en_US; lsd=WW[...]; c_user=2101[...]
GET請求的URL是"http://facebook.com/",瀏覽器經過User-Agent消息頭標識本身,並聲明可接受的響應類型(Accept和Accept-Encoding消息頭),Connection消息頭要求服務器保持TCP鏈接打開,以便處理下一步請求。
請求包含了瀏覽器對該域名的cookie,你可能已經知道,cookie是key-value成對出現的,它能夠跟蹤不一樣頁面請求之間網站的狀態,所以cookie保存了登陸的用戶名,服務器會給用戶分配一段密碼數字,cookie在客戶端上實際是一個文本文件,它會跟隨每一個請求發給服務器。
有許多工具能夠查看原始HTTP請求和對應的響應,我最喜歡的是fiddler,也許你想說的是FireBug,沒錯,工具不少,就看我的喜愛了,這些工具都能幫助你優化網站。
除了GET請求外,你可能還熟悉另外一種類型的請求- POST請求,它一般用於提交表單,GET請求經過URL發送它的參數(如http://robozzle.com/puzzle.aspx?id=85),POST請求在請求主體中發送它的參數。
在URL"http://facebook.com/"中的斜線很是重要,在這裏,瀏覽器能夠安全地添加斜線,對於"http://example.com/folderOrFile"這種格式的URL,瀏覽器不能自動添加一個斜線,由於尚不清楚folderOrFile是一個文件夾仍是一個文件,在這種狀況下,瀏覽器不會擅自添加斜線,服務器將會以重定向做爲響應,致使沒必要要的來回通訊。
四、Facebook服務器以一個永久重定向響應
圖 5
下面是Facebook服務器向瀏覽器請求發回的響應:
HTTP/1.1 301 Moved Permanently Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Expires: Sat, 01 Jan 2000 00:00:00 GMT Location: P3P: CP="DSP LAW" Pragma: no-cache Set-Cookie: made_write_conn=deleted; expires=Thu, 12-Feb-2009 05:09:50 GMT; path=/; domain=.facebook.com; httponly Content-Type: text/html; charset=utf-8 X-Cnection: close Date: Fri, 12 Feb 2010 05:09:51 GMT Content-Length: 0
服務器以301永久移走響應告訴瀏覽器應轉到"http://www.facebook.com/"而不是"http://facebook.com/"。
你可能會問,爲何服務器要堅持用重定向進行響應呢?爲何不用用戶想看的網頁進行響應呢?
一個緣由是搜索引擎排名,若是相同網頁有兩個URL,如http://www.igoro.com/和http://igoro.com/,搜索引擎會將他倆看做是兩個不一樣的網站,分攤到每一個URL的入站鏈接就要少得多,從而下降了網站的排名,搜索引擎理解永久重定向(301),將會把來自這兩個源的入站鏈接合併成一個排名。
一樣,相同內容對應的URL太多也利於緩存,若是某段內容有多個名字,在緩存中可能也會出現屢次。
五、瀏覽器跟隨重定向
圖 6
瀏覽器如今知道"http://www.facebook.com/"纔是正確的URL,因而發出第二個GET請求。
GET http://www.facebook.com/ HTTP/1.1 Accept: application/x-ms-application, image/jpeg, application/xaml+xml, [...] Accept-Language: en-US User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...] Accept-Encoding: gzip, deflate Connection: Keep-Alive Cookie: lsd=XW[...]; c_user=21[...]; x-referer=[...] Host:
消息頭和第一個請求的含義同樣,就再也不囉嗦了。
六、服務器處理請求
圖 7
服務器將會收到GET請求並進行處理,而後發回響應,看起來是一個很是簡單的操做,但實際上在這個期間發生了許多有趣的事情。
◆Web服務器軟件
Web服務器軟件(如IIS或Apache)收到HTTP請求後,當即肯定由哪一個請求處理程序來處理這個請求,請求處理程序讀取請求,生成HTML。
舉一個最簡單的例子,請求處理程序能夠保存在一個文件中,其結構和URL結構徹底對應,如http://example.com/folder1/page1.aspx URL映射到文件/httpdocs/folder1/page1.aspx,Web服務器軟件也能夠配置,將URL手工映射到請求處理程序,所以page1.aspx的公共URL應該是http://example.com/folder1/page1。
◆請求處理程序
請求處理程序讀取請求,它的參數和cookie,它可能會讀取和更新服務器上的某些數據,而後生成一個HTML頁面做爲響應。
每一個動態網站面臨的一個有趣的困難是如何保存數據,小網站一般只有一個SQL數據庫來保存數據,但大型網站必須將數據庫部署到多臺服務器上,解決辦法包括水平分區(根據主鍵,將一張表拆分到多個數據庫),複製和使用簡化數據庫(不追求一致性)。
保持數據廉價更新的一個技術是使用批處理做業,例如,Facebook會及時更新新聞消息源,但"你可能知道"功能可能只須要每晚進行更新(我猜的,我也不知道真實狀況如何),批處理做業更新會產生一些過期的不重要的數據,但它使數據更新更快,更簡單。
七、服務器發回HTML響應
圖 8
下面是服務器生成併發回的一個響應:
HTTP/1.1 200 OK
Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,
pre-check=0
Expires: Sat, 01 Jan 2000 00:00:00 GMT
P3P: CP="DSP LAW"
Pragma: no-cache
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
X-Cnection: close
Transfer-Encoding: chunked
Date: Fri, 12 Feb 2010 09:05:55 GMT2b3????????T?n?@????[...]
The entire response is 36 kB, the bulk of them in the byte blob at the end that I trimmed.
The Content-Encoding header tells the browser that the response body is compressed using the gzip algorithm.After decompressing the blob, you'll see the HTML you'd expect:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
id="facebook" class=" no_js">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-language" content="en" />
...
除了壓縮外,消息頭指定是否以及如何緩存頁面,cookie設置(在這個響應中沒有),隱私信息等等。
注意消息頭中的Content-Typt設置成text/html了,它告訴瀏覽器以HTML呈現響應的內容,而不是做爲一個文件下載,瀏覽器經過消息頭決定如何解釋響應的內容,但也會考慮其餘因素,如URL擴展。
八、瀏覽器開始渲染HTML
在瀏覽器未接收完整個HTML文檔以前,它就開始渲染了。
圖 9
九、瀏覽器發送嵌入到HTML中的對象請求
圖 10
在瀏覽器渲染HTML時,它會發現還須要訪問其它URL,瀏覽器繼續爲這些資源發出GET請求,下面是我訪問facebook.com時進一步訪問的一些URL:
◆圖像 … ◆CSS樣式表 … ◆JavaScript文件 …
每一個URL都會經歷訪問HTML頁面相似的過程,所以,瀏覽器會在DNS中查找域名,發送請求,跟隨重定向等。
但靜態文件 - 和動態頁面不同 - 容許瀏覽器緩存,有些文件在下一次訪問時可直接從瀏覽器緩存中提取,不用聯繫服務器,瀏覽器知道某個特定文件的緩存有效期,由於第一次從服務器返回到瀏覽器時就包含了Expires頭信息,此外,每一個響應可能也包含一個相似版本號的ETag頭,若是瀏覽器看到一個ETag,它會當即中止傳輸文件。
你能猜到URL中的fbcdn.net表明什麼嗎?沒錯,它表示Facebook內容交付網絡,Facebook使用內容交付網絡(CDN)分發靜態內容 - 圖像,樣式表和JavaScript文件,所以,文件將被複制到全球許多服務器上。
靜態內容一般會佔用網站的大量帶寬,但也很容易被複制到CDN網絡中的加速節點,通常狀況下,網站會使用第三方CDN提供商,而不是本身運營CDN,例如,Facebook的靜態文件由世界最大的CDN提供商Akamai託管。
咱們仍是舉一個例子,當你ping static.ak.fbcdn.net時,你會從akamai.net服務器獲得一個應答,一樣,若是你分屢次ping URL,可能會從不一樣的服務器獲得應答,這說明背後的負載均衡正在發生做用。
十、瀏覽器進一步發送異步(Ajax)請求
圖 11
根據Web 2.0的精神,即便頁面渲染完畢後,客戶端也要繼續和服務器通訊。
例如,Facebook chat會持續更新你的朋友列表(他們登陸和退出都會很快反饋給你),在你瀏覽器中執行的JavaScript向服務器發送一個異步請求,異步請求是經過編程實現的指向特定URL的GET或POST請求,仍是以Facebook爲例,客戶端向http://www.facebook.com/ajax/chat/buddy_list.php發送一個POST請求,獲取你的在線朋友列表。
這種模式有時指的是Ajax,Ajax表示異步JavaScript和XML,但服務器不必定非要以XML格式進行響應,例如,Facebook返回JavaScript代碼片斷響應異步請求。
Fiddler工具容許你查看瀏覽器發送的異步請求,實際上,你不但能夠觀察請求,並且還能夠修改這些請求並進行重發,所以能夠輕鬆欺騙Ajax請求,許多在線遊戲的開發人員也所以而鬱悶不已。
Facebook chat提供了一個有趣的Ajax問題示例:將數據從服務器推向客戶端。由於HTTP是一個請求-響應協議,聊天服務器不能將新消息推送給客戶端,相反,客戶端必須每隔幾秒從服務器去取數據,以瞭解是否有新消息到達。
長輪詢在這種情景中對下降服務器負載頗有用,輪詢時若是服務器沒有任何新消息,它就不發回應答,同時,若是該客戶端有新消息到達,服務器會發現未完成的請求,並返回消息做爲響應。
原文出處:http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/
原文名:What really happens when you navigate to a URL
做者:Igor Ostrovsky