1.在瀏覽器中輸入URL
這一切都從這里開始:
2.瀏覽器查找域名的IP地址
導航的第一步是找出訪問域的IP地址。DNS查找進行如下:
- 瀏覽器緩存 -瀏覽器緩存DNS記錄一段時間。有趣的是,操作系統並沒有告訴瀏覽器每個DNS記錄的生存時間,因此瀏覽器會將其緩存一段固定的時間(瀏覽器間隔2到30分鍾)。
- 操作系統緩存 - 如果瀏覽器緩存不包含所需的記錄,則瀏覽器進行系統調用(Windows中的gethostbyname)。操作系統有自己的緩存。
- 路由器緩存 - 請求繼續到您的路由器,路由器通常具有自己的DNS緩存。
- ISP DNS緩存 - 檢查的下一個位置是緩存ISP的DNS服務器。有緩存,自然。
- 遞歸搜索 - 您的ISP的DNS服務器開始遞歸搜索,從根名稱服務器通過.com頂級名稱服務器到Facebook的名稱服務器。通常,DNS服務器將在緩存中具有.com名稱服務器的名稱,因此對根名稱服務器的命中是不必要的。
以下是遞歸DNS搜索的示意圖:
3.瀏覽器向Web服務器發送HTTP請求
可以非常確定Facebook的主頁將不會從瀏覽器緩存中提供,因為動態頁面會非常快速或即時(過期日期設置為過期)。
因此,瀏覽器會將此請求發送到Facebook服務器:
GET http://facebook.com/ HTTP / 1.1 接受: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 連接:保持活力 主持人:facebook.com 餅干:DATR = 1265876274- [...] ; 區域設置= EN_US; LSD = WW [...] ; c_user = 2101 [...]
GET請求命名要提取的URL : “http://facebook.com/”。瀏覽器識別自己(User-Agent頭),並說明它將接受什么類型的響應(Accept和Accept-Encoding標頭)。該連接頭要求服務器以保持TCP連接開放的進一步請求。
該請求還包含瀏覽器對此域的Cookie。您可能已經知道,Cookie是跟蹤不同頁面請求之間的網站狀態的鍵值對。因此,Cookie會存儲登錄用戶的名稱,由服務器分配給用戶的密碼,用戶的某些設置等。Cookie將存儲在客戶端上的文本文件中,並發送到服務器與每個請求。
4.Facebook服務器以永久重定向方式進行響應
這是Facebook服務器發送回瀏覽器請求的響應:
HTTP / 1.1 301永久移動 Cache-Control:private,no-store,no-cache,must-revalidate,post-check = 0, 前檢查= 0 過期日:2000年1月1日星期六00:00:00 GMT 位置:http://www.facebook.com/ P3P:CP =“DSP LAW” Pragma:不緩存 Set-Cookie:made_write_conn = deleted; expires =星期四,2009年2月12日05:09:50 GMT; 路徑= /; 域= .facebook.com; 僅Http 內容類型:text / html; 字符集= utf-8的 X-Cnection:關閉 日期:2010年2月12日,星期五05:09:51 GMT 內容長度:0
服務器回復了301移動永久響應,告訴瀏覽器轉到“http://www.facebook.com/”而不是“http://facebook.com/”。
有一些有趣的原因為什么服務器堅持重定向,而不是立即響應用戶想要看到的網頁。
一個原因與搜索引擎排名有關。請參閱如果同一頁面有兩個URL,例如http://www.igoro.com/和http://igoro.com/,搜索引擎可能會認為它們是兩個不同的網站,每個網站的入站鏈路較少,因此排名較低。搜索引擎了解永久重定向(301),並將來自兩個來源的傳入鏈接組合成單個排名。
此外,同一內容的多個URL不是緩存友好的。當一段內容有多個名稱時,它會在緩存中潛在出現多次。
5.瀏覽器遵循重定向
瀏覽器現在知道“http://www.facebook.com/”是正確的URL,因此它會發出另一個GET請求:
GET http://www.facebook.com/ HTTP / 1.1 接受:application / x-ms-application,image / jpeg,application / xaml + xml,[...] 接受語言:en-US 用戶代理:Mozilla / 4.0(兼容; MSIE 8.0; Windows NT 6.1; WOW64; [...] Accept-Encoding:gzip,deflate 連接:保持活力 Cookie:lsd = XW [...] ; c_user = 21 [...] ; x-referer = [...] 主持人:www.facebook.com
標題的含義與第一個請求相同。
6.服務器'處理'請求
服務器將收到GET請求,處理它並發送回應。
這似乎是一個簡單的任務,但事實上,這里發生了很多有趣的事情 - 即使在像我的博客這樣的簡單網站上,更不用說像Facebook這樣大規模擴展的網站。
- Web服務器軟件
Web服務器軟件(例如IIS或Apache)接收HTTP請求,並決定執行哪個請求處理程序來處理此請求。請求處理程序是一個讀取請求並生成響應的HTML的程序(在ASP.NET,PHP,Ruby,...中)。在最簡單的情況下,請求處理程序可以存儲在結構反映URL結構的文件層次結構中,例如http://example.com/folder1/page1.aspx URL將映射到file / httpdocs / folder1 / page1的.aspx。也可以配置Web服務器軟件,以便將URL手動映射到請求處理程序,因此page1.aspx的公共URL可以是http://example.com/folder1/page1。
- 請求處理程序
請求處理程序讀取請求,其參數和Cookie。它將讀取並可能更新存儲在服務器上的一些數據。然后,請求處理程序將生成一個HTML響應。
每個動態網站面臨的一個有趣的難題是如何存儲數據。較小的站點通常會有一個SQL數據庫來存儲他們的數據,但存儲大量數據和/或有許多訪問者的站點必須找到一種在多台機器上分割數據庫的方式。解決方案包括分片(基於主鍵分割多個數據庫的表),復制以及使用弱化一致性語義的簡化數據庫。
保持數據更新便宜的一種技術是將一些工作推遲到批處理作業。例如,Facebook必須及時更新新聞源,但支持“您可能認識的人”功能的數據可能只需要每晚更新(我的猜測,我實際上並不知道如何實現此功能)。批量作業更新導致一些不太重要的數據的陳舊,但可以使數據更新更快更簡單。
7.服務器發回一個HTML響應
以下是服務器生成並發回的響應:
HTTP / 1.1 200 OK Cache-Control:private,no-store,no-cache,must-revalidate,post-check = 0, 前檢查= 0 過期日:2000年1月1日星期六00:00:00 GMT P3P:CP =“DSP LAW” Pragma:不緩存 內容編碼:gzip 內容類型:text / html; 字符集= utf-8的 X-Cnection:關閉 轉移編碼:分塊 日期:2010年2月12日,星期五09:05:55 GMT 2B3
Tn的@ [...]
整個響應是36 kB,大部分在我修剪結束的字節blob中。
的內容編碼頭告訴該響應體用gzip算法壓縮的瀏覽器。解壓縮Blob后,您會看到您期望的HTML:
<!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” 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-Type設置為text / html的標題。標題指示瀏覽器將響應內容呈現為HTML,而不是將其作為文件下載。瀏覽器將使用標題來決定如何解釋響應,但也會考慮其他因素,例如URL的擴展。
8.瀏覽器開始渲染HTML
即使在瀏覽器收到整個HTML文檔之前,它也開始渲染網站:
9.瀏覽器發送嵌入HTML的對象的請求
當瀏覽器呈現HTML時,它會注意到需要提取其他URL的標簽。瀏覽器將發送GET請求以檢索這些文件。
以下是我訪問facebook.com的幾個網址:
- 圖片
http://static.ak.fbcdn.net/rsrc.php/z12E0/hash/8q2anwu7.gif
http://static.ak.fbcdn.net/rsrc.php/zBS5C/hash/7hwy7at6.gif
... - CSS樣式表
http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css
http://static.ak.fbcdn.net/rsrc.php/zANE1/hash/cvtutcee.css
... - JavaScript文件
http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js
http://static.ak.fbcdn.net/rsrc.php/z6R9L/hash/cq2lgbs8.js
...
這些URL中的每一個將通過與HTML頁面通過的過程類似的過程。因此,瀏覽器將在DNS中查找域名,向URL發送請求,重定向等。
但是,靜態文件(與動態頁面不同)允許瀏覽器緩存它們。一些文件可以從緩存中提供,而不需要聯系服務器。瀏覽器知道緩存特定文件多長時間,因為返回文件的響應包含一個Expires頭。此外,每個響應還可以包含一個類似版本號的ETag標頭 - 如果瀏覽器看到已經具有的文件版本的ETag,則可以立即停止傳輸。
你可以猜測網址中的“fbcdn.net”代表什么?值得一提的是,這意味着“Facebook內容傳送網絡”。Facebook使用內容傳送網絡(CDN)來分發靜態內容 - 圖像,樣式表和JavaScript文件。因此,這些文件將被復制到全球許多機器。
靜態內容通常代表站點的大部分帶寬,並且可以輕松地復制到CDN上。通常,網站將使用第三方CDN提供商,而不是自己運行CND。例如,Facebook的靜態文件由最大的CDN提供商Akamai主辦。
作為演示,當您嘗試ping static.ak.fbcdn.net時,您將收到來自akamai.net服務器的響應。此外,有趣的是,如果您ping了URL幾次,可能會收到來自不同服務器的響應,這表明后台發生的負載平衡。
10.瀏覽器發送進一步的異步(AJAX)請求
以Web 2.0的精神,即使在頁面呈現之后,客戶端仍然繼續與服務器進行通信。
例如,Facebook聊天將繼續更新您登錄的朋友的名單,因為他們來了。要更新已登錄的朋友列表,瀏覽器中執行的JavaScript必須向服務器發送異步請求。異步請求是一種程序化構造的GET或POST請求,轉到特殊的URL。在Facebook示例中,客戶端向http://www.facebook.com/ajax/chat/buddy_list.php發送POST請求,以獲取在線的朋友的列表。
這種模式有時被稱為“AJAX”,它代表“異步JavaScript和XML”,盡管沒有特別的理由為什么服務器必須將響應格式化為XML。例如,Facebook響應異步請求返回JavaScript代碼片段。
除此之外,提示工具可讓您查看瀏覽器發送的異步請求。實際上,你不僅可以被動地觀察請求,還可以修改並重新發送。事實上,這是一個易於“欺騙”AJAX請求的事實,對於使用記分牌的在線游戲的開發者來說,造成了很大的傷害。(顯然,請不要以這種方式作弊。)
Facebook聊天提供了一個AJAX有趣的問題的例子:將數據從服務器推送到客戶端。由於HTTP是請求 - 響應協議,因此聊天服務器無法將新消息推送到客戶端。相反,客戶端必須每隔幾秒輪詢服務器,以查看是否有新消息到達。
長時間輪詢是減少這些類型場景中服務器負載的有趣技術。如果服務器在輪詢時沒有任何新消息,則根本不會發回響應。而且,如果在超時期限內收到了一個此客戶端的消息,服務器將發現未完成的請求並返回消息。