做爲軟件開發人員,您確定會看到網絡應用程序如何工做以及涉及哪些技術的高級畫面:瀏覽器,HTTP,HTML,Web服務器,請求處理程序等。php
在本文中,咱們將深刻了解訪問URL時發生的事件順序。css
這一切都從這裏開始:html
導航的第一步是找出訪問域的IP地址。DNS查找進行以下:ajax
如下是遞歸DNS搜索的示意圖:算法
關於DNS的一個使人擔心的是,像wikipedia.org或facebook.com這樣的整個域彷佛映射到一個IP地址。幸運的是有辦法減輕瓶頸:數據庫
大多數DNS服務器自己使用anycast來實現DNS查找的高可用性和低延遲。瀏覽器
您能夠很是肯定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將存儲在客戶端上的文本文件中,併發送到服務器與每一個請求。
有各類工具可以讓您查看原始的HTTP請求和相應的響應。我最喜歡的查看原始HTTP流量的工具是輕鬆的,但還有許多其餘工具(例如FireBug)。這些工具在優化網站時是很是有幫助的。
除了GET請求以外,您可能熟悉的其餘類型的請求是POST請求,一般用於提交表單。GET請求經過URL發送其參數(例如:http://robozzle.com/puzzle.aspx ?id = 85)。POST請求在請求正文中發送其參數,就在頭文件下方。
網址「http://facebook.com/」中的尾部斜槓很重要。在這種狀況下,瀏覽器能夠安全地添加斜槓。對於http://example.com/folderOrFile表單的網址,瀏覽器沒法自動添加斜槓,由於folderOrFile是不是文件夾或文件不清楚。在這種狀況下,瀏覽器將不用斜槓訪問URL,服務器將以重定向進行響應,致使沒必要要的往返。
這是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不是緩存友好的。當一段內容有多個名稱時,它會在緩存中潛在出現屢次。
瀏覽器如今知道「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
標題的含義與第一個請求相同。
服務器將收到GET請求,處理它併發送回應。
這彷佛是一個簡單的任務,但事實上,這裏發生了不少有趣的事情 - 即便在像個人博客這樣的簡單網站上,更不用說像Facebook這樣大規模擴展的網站。
在最簡單的狀況下,請求處理程序能夠存儲在結構反映URL結構的文件層次結構中,例如http://example.com/folder1/page1.aspx URL將映射到file / httpdocs / folder1 / page1的.aspx。也能夠配置Web服務器軟件,以便將URL手動映射到請求處理程序,所以page1.aspx的公共URL能夠是http://example.com/folder1/page1。
每一個動態網站面臨的一個有趣的難題是如何存儲數據。較小的站點一般會有一個SQL數據庫來存儲他們的數據,但存儲大量數據和/或有許多訪問者的站點必須找到一種在多臺機器上分割數據庫的方式。解決方案包括分片(基於主鍵分割多個數據庫的表),複製以及使用弱化一致性語義的簡化數據庫。
保持數據更新便宜的一種技術是將一些工做推遲到批處理做業。例如,Facebook必須及時更新新聞源,但支持「您可能認識的人」功能的數據可能只須要每晚更新(個人猜想,我實際上並不知道如何實現此功能)。批量做業更新致使一些不過重要的數據的陳舊,但可使數據更新更快更簡單。
如下是服務器生成併發回的響應:
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的擴展。
即便在瀏覽器收到整個HTML文檔以前,它也開始渲染網站:
當瀏覽器呈現HTML時,它會注意到須要提取其餘URL的標籤。瀏覽器將發送GET請求以檢索這些文件。
如下是我訪問facebook.com的幾個網址:
這些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幾回,可能會收到來自不一樣服務器的響應,這代表後臺發生的負載平衡。
以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是請求 - 響應協議,所以聊天服務器沒法將新消息推送到客戶端。相反,客戶端必須每隔幾秒輪詢服務器,以查看是否有新消息到達。
長時間輪詢是減小這些類型場景中服務器負載的有趣技術。若是服務器在輪詢時沒有任何新消息,則根本不會發迴響應。並且,若是在超時期限內收到了一個此客戶端的消息,服務器將發現未完成的請求並返回消息。