從一道百度面試題到分析輸入url到頁面返回的過程(或者查詢返回過程)

轉自http://blog.csdn.net/wdzxl198/article/details/11265475


最近看到一個題目,是當在瀏覽器中輸入一個url後回車,後臺發生了什麼?比如輸入url後,你看到了百度的首頁,那麼這一切是如何發生的呢?

這個問題之前、最近、我想以後肯定還會被問到,或者問到這樣的題目,如果在百度框裏輸入查詢的字符串開始,是怎麼返回你需要的東西呢。

那這什麼個過程呢(這個問題我在之後的博客中在寫)?


網上各種的說法,不外乎這麼幾種

第一種簡單的說呢就是這樣的:


第一步:客戶機提出域名解析請求,並將該請求發送給本地的域名服務器。
第二步:當本地的域名服務器收到請求後,就先查詢本地的緩存,如果有該紀錄項,則本地的域名服務器就直接把查詢的結果返回。
第三步:如果本地的緩存中沒有該紀錄,則本地域名服務器就直接把請求發給根域名服務器,然後根域名服務器再返回給本地域名服務器一個所查詢域(根的子域)的主域名服務器的地址。
第四步:本地服務器再向上一步返回的域名服務器發送請求,然後接受請求的服務器查詢自己的緩存,如果沒有該紀錄,則返回相關的下級的域名服務器的地址。
第五步:重複第四步,直到找到正確的紀錄。

第二種,更詳細些的,英文的但相信你很容易看明白

1.enter the url to the address bar

2.a request will be sent to the DNS server based on your network configuration

3.DNS will route you to the real IP of the domain name

4.a request(with complete Http header) will be sent to the server(with 3's IP to identify)'s 80 port(suppose we don't specify another port)

5.server will search the listening ports and forward the request to the app which is listening to 80 port(let's say nginx here) or to another server(then 3's server will be like a load balancer)

6.nginx will try to match the url to its configuration and serve as an static page directly, or invoke the corresponding script intepreter(e.g PHP/Python) or other app to get the dynamic content(with DB query, or other logics)

7.a html will be sent back to browser with a complete Http response header

8.browser will parse the DOM of html using its parser

9.external resources(JS/CSS/images/flash/videos..) will be requested in sequence(or not?)

10.for JS, it will be executed by JS engine

11.for CSS, it will be rendered by CSS engine and HTML's display will be adjusted based on the CSS(also in sequence or not?)

12.if there's an iframe in the DOM, then a separate same process will be executed from step 1-12


第三種的,

1.browser checks cache; if requested object is in cache and is fresh, skip to #9

2.browser asks OS for server's IP address

3.OS makes a DNS lookup and replies the IP address to the browser

4.browser opens a TCP connection to server (this step is much more complex with HTTPS)

5.browser sends the HTTP request through TCP connection

6.browser receives HTTP response and may close the TCP connection, or reuse it for another request

7.browser checks if the response is a redirect (3xx result status codes), authorization request (401), error (4xx and 5xx), etc.; these are handled differently from normal responses (2xx)

8.if cacheable, response is stored in cache

9.browser decodes response (e.g. if it's gzipped)

10.browser determines what to do with response (e.g. is it a HTML page, is it an image, is it a sound clip?)

11.browser renders response, or offers a download dialog for unrecognized types

咱們仔細的說一下整個過程吧,這裏我參考一篇國外的文章,就是這個大牛的,題目是What really happens when you navigate to a URL,鏈接見文章最後的參考資料


1. You enter a URL into the browser(輸入一個url地址)

<pre name="code" id="answer-content-693936476" class="answer-text mb-10" style="margin-top:0px; margin-bottom:10px; padding:0px; word-wrap:break-word; background-color:rgb(255,255,255)"><p style="font-size:13px; margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(17,17,17); font-family:Verdana,Arial,Helvetica,sans-serif; line-height:23px"><pre name="code" id="answer-content-693936476" class="answer-text mb-10" style="margin-top:0px; margin-bottom:10px; padding:0px; word-wrap:break-word; background-color:rgb(255,255,255)"><p style="font-size:13px; margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(17,17,17); font-family:Verdana,Arial,Helvetica,sans-serif; line-height:23px"><img src="http://igoro.com/wordpress/wp-content/uploads/2010/02/image4.png" alt="image" title="image" style="margin:0px; padding:0px; border:0px; width:562px; height:98px" width="591" height="103" border="0" /></p>


2.The browser looks up the IP address for the domain name(瀏覽器查找域名的ip地址)
<p style="font-size:13px; margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(17,17,17); font-family:Verdana,Arial,Helvetica,sans-serif; line-height:23px"><img src="http://igoro.com/wordpress/wp-content/uploads/2010/02/image13.png" alt="image" title="image" style="margin:0px; padding:0px; border:0px; display:inline" width="228" height="96" border="0" /></p>
導航的第一步是通過訪問的域名找出其IP地址。DNS查找過程如下: 瀏覽器緩存 – 瀏覽器會緩存DNS記錄一段時間。 有趣的是,操作系統沒有告訴瀏覽器儲存DNS記錄的時間,這樣不同瀏覽器會儲存個自固定的一個時間(2分鐘到30分鐘不等)。 系統緩存 – 如果在瀏覽器緩存裏沒有找到需要的記錄,瀏覽器會做一個系統調用(windows裏是gethostbyname)。這樣便可獲得系統緩存中的記錄。 路由器緩存 – 接着,前面的查詢請求發向路由器,它一般會有自己的DNS緩存。 ISP DNS 緩存 – 接下來要check的就是ISP緩存DNS的服務器。在這一般都能找到相應的緩存記錄。 遞歸搜索 – 你的ISP的DNS服務器從跟域名服務器開始進行遞歸搜索,從.com頂級域名服務器到Facebook的域名服務器。一般DNS服務器的緩存中會有.com域名服務器中的域名,所以到頂級服務器的匹配過程不是那麼必要了。DNS遞歸查找如下圖所示:
<p style="font-size:13px; margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(17,17,17); font-family:Verdana,Arial,Helvetica,sans-serif; line-height:23px"><img src="http://igoro.com/wordpress/wp-content/uploads/2010/02/500pxAn_example_of_theoretical_DNS_recursion_svg.png" alt="500px-An_example_of_theoretical_DNS_recursion_svg" title="500px-An_example_of_theoretical_DNS_recursion_svg" style="margin:0px; padding:0px; border:0px; display:inline" width="500" height="178" border="0" /></p>
DNS有一點令人擔憂,這就是像wikipedia.org 或者 facebook.com這樣的整個域名看上去只是對應一個單獨的IP地址。還好,有幾種方法可以消除這個瓶頸: 循環DNS是DNS查找時返回多個IP時的解決方案。舉例來說,Facebook.com實際上就對應了四個IP地址。 負載平衡器是以一個特定IP地址進行偵聽並將網絡請求轉發到集羣服務器上的硬件設備。 一些大型的站點一般都會使用這種昂貴的高性能負載平衡器。 地理 DNS 根據用戶所處的地理位置,通過把域名映射到多個不同的IP地址提高可擴展性。這樣不同的服務器不能夠更新同步狀態,但映射靜態內容的話非常好。 Anycast是一個IP地址映射多個物理主機的路由技術。 美中不足,Anycast與TCP協議適應的不是很好,所以很少應用在那些方案中。大多數DNS服務器使用Anycast來獲得高效低延遲的DNS查找。3. The browser sends a HTTP request to the web server(瀏覽器給web服務器發送一個HTTP請求)
<p style="font-size:13px; margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(17,17,17); font-family:Verdana,Arial,Helvetica,sans-serif; line-height:23px"><img src="http://igoro.com/wordpress/wp-content/uploads/2010/02/image22.png" alt="image" title="image" style="margin:0px; padding:0px; border:0px; display:inline" width="216" height="95" border="0" /></p>
因爲像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 頭), 和它希望接受什麼類型的相應 (Acceptand Accept-Encoding 頭). Connection頭要求服務器爲了後邊的請求不要關閉TCP連接。

請求中也包含瀏覽器存儲的該域名的cookies。可能你已經知道,在不同頁面請求當中,cookies是與跟蹤一個網站狀態相匹配的鍵值。這樣cookies會存儲登錄用戶名,服務器分配的密碼和一些用戶設置等。Cookies會以文本文檔形式存儲在客戶機裏,每次請求時發送給服務器。

用來看原始HTTP請求及其相應的工具很多。作者比較喜歡使用fiddler,當然也有像FireBug這樣其他的工具。這些軟件在網站優化時會幫上很大忙。
除了獲取請求,還有一種是發送請求,它常在提交表單用到。發送請求通過URL傳遞其參數(e.g.: http://robozzle.com/puzzle.aspx?id=85)。發送請求在請求正文頭之後發送其參數。

像“http://facebook.com/”中的斜槓是至關重要的。這種情況下,瀏覽器能安全的添加斜槓。而像“http: //example.com/folderOrFile”這樣的地址,因爲瀏覽器不清楚folderOrFile到底是文件夾還是文件,所以不能自動添加 斜槓。這時,瀏覽器就不加斜槓直接訪問地址,服務器會響應一個重定向,結果造成一次不必要的握手。 



4. The facebook server responds with a permanent redirect (facebook服務的永久重定向響應)

image

圖中所示爲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: http://www.facebook.com/
 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/”。

爲什麼服務器一定要重定向而不是直接發會用戶想看的網頁內容呢?這個問題有好多有意思的答案。

其中一個原因跟搜索引擎排名有 關。你看,如果一個頁面有兩個地址,就像http://www.igoro.com/ 和http://igoro.com/,搜索引擎會認爲它們是兩個網站,結果造成每一個的搜索鏈接都減少從而降低排名。而搜索引擎知道301永久重定向是 什麼意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網站排名下。

還有一個是用不同的地址會造成緩存友好性變差。當一個頁面有好幾個名字時,它可能會在緩存裏出現好幾次。

5. The browser follows the redirect(瀏覽器跟蹤重定向地址)

image

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

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: www.facebook.com

頭信息以之前請求中的意義相同。

6. The server ‘handles’ the request(服務器“處理”請求)

image

服務器接收到獲取請求,然後處理並返回一個響應。

這表面上看起來是一個順向的任務,但其實這中間發生了很多有意思的東西- 就像作者博客這樣簡單的網站,何況像facebook那樣訪問量大的網站呢!

  • Web 服務器軟件
    web服務器軟件(像IIS和阿帕奇)接收到HTTP請求,然後確定執行什麼請求處理來處理它。請求處理就是一個能夠讀懂請求並且能生成HTML來進行響應的程序(像ASP.NET,PHP,RUBY...)。

    舉 個最簡單的例子,需求處理可以以映射網站地址結構的文件層次存儲。像http://example.com/folder1/page1.aspx這個地 址會映射/httpdocs/folder1/page1.aspx這個文件。web服務器軟件可以設置成爲地址人工的對應請求處理,這樣 page1.aspx的發佈地址就可以是http://example.com/folder1/page1。

  • 請求處理
    請求處理閱讀請求及它的參數和cookies。它會讀取也可能更新一些數據,並講數據存儲在服務器上。然後,需求處理會生成一個HTML響應。

所 有動態網站都面臨一個有意思的難點 -如何存儲數據。小網站一半都會有一個SQL數據庫來存儲數據,存儲大量數據和/或訪問量大的網站不得不找一些辦法把數據庫分配到多臺機器上。解決方案 有:sharding (基於主鍵值講數據表分散到多個數據庫中),複製,利用弱語義一致性的簡化數據庫。

委 託工作給批處理是一個廉價保持數據更新的技術。舉例來講,Fackbook得及時更新新聞feed,但數據支持下的“你可能認識的人”功能只需要每晚更新 (作者猜測是這樣的,改功能如何完善不得而知)。批處理作業更新會導致一些不太重要的數據陳舊,但能使數據更新耕作更快更簡潔。

7. The server sends back a HTML response(服務器發回一個HTML響應)

image

圖中爲服務器生成並返回的響應:

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 GMT
 
 2b3Tn@[...]

整個響應大小爲35kB,其中大部分在整理後以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" />
 ...

關於壓縮,頭信息說明了是否緩存這個頁面,如果緩存的話如何去做,有什麼cookies要去設置(前面這個響應裏沒有這點)和隱私信息等等。

請注意報頭中把Content-type設置爲“text/html”。報頭讓瀏覽器將該響應內容以HTML形式呈現,而不是以文件形式下載它。瀏覽器會根據報頭信息決定如何解釋該響應,不過同時也會考慮像URL擴展內容等其他因素。

8. The browser begins rendering the HTML(瀏覽器開始顯示HTML)

在瀏覽器沒有完整接受全部HTML文檔時,它就已經開始顯示這個頁面了:

image

9. The browser sends requests for objects embedded in HTML(瀏覽器發送獲取嵌入在HTML中的對象)

image

在瀏覽器顯示HTML時,它會注意到需要獲取其他地址內容的標籤。這時,瀏覽器會發送一個獲取請求來重新獲得這些文件。

下面是幾個我們訪問facebook.com時需要重獲取的幾個URL:

  • 圖片
    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

這些地址都要經歷一個和HTML讀取類似的過程。所以瀏覽器會在DNS中查找這些域名,發送請求,重定向等等...

但 不像動態頁面那樣,靜態文件會允許瀏覽器對其進行緩存。有的文件可能會不需要與服務器通訊,而從緩存中直接讀取。服務器的響應中包含了靜態文件保存的期限 信息,所以瀏覽器知道要把它們緩存多長時間。還有,每個響應都可能包含像版本號一樣工作的ETag頭(被請求變量的實體值),如果瀏覽器觀察到文件的版本 ETag信息已經存在,就馬上停止這個文件的傳輸。

試着猜猜看“fbcdn.net”在地址中代表什麼?聰明的答案是"Facebook內容分發網絡"。Facebook利用內容分發網絡(CDN)分發像圖片,CSS表和JavaScript文件這些靜態文件。所以,這些文件會在全球很多CDN的數據中心中留下備份。

靜態內容往往代表站點的帶寬大小,也能通過CDN輕鬆的複製。通常網站會使用第三方的CDN。例如,Facebook的靜態文件由最大的CDN提供商Akamai來託管。

舉例來講,當你試着ping static.ak.fbcdn.net的時候,可能會從某個akamai.net服務器上獲得響應。有意思的是,當你同樣再ping一次的時候,響應的服務器可能就不一樣,這說明幕後的負載平衡開始起作用了。

10. The browser sends further asynchronous (AJAX) requests(瀏覽器發送異步(AJAX)請求)

image

在Web 2.0偉大精神的指引下,頁面顯示完成後客戶端仍與服務器端保持着聯繫。

以 Facebook聊天功能爲例,它會持續與服務器保持聯繫來及時更新你那些亮亮灰灰的好友狀態。爲了更新這些頭像亮着的好友狀態,在瀏覽器中執行的 JavaScript代碼會給服務器發送異步請求。這個異步請求發送給特定的地址,它是一個按照程式構造的獲取或發送請求。還是在Facebook這個例 子中,客戶端發送給http://www.facebook.com/ajax/chat/buddy_list.php一個發佈請求來獲取你好友裏哪個 在線的狀態信息。

提起這個模式,就必須要講講"AJAX"-- “異步JavaScript 和 XML”,雖然服務器爲什麼用XML格式來進行響應也沒有個一清二白的原因。再舉個例子吧,對於異步請求,Facebook會返回一些JavaScript的代碼片段。

除了其他,fiddler這個工具能夠讓你看到瀏覽器發送的異步請求。事實上,你不僅可以被動的做爲這些請求的看客,還能主動出擊修改和重新發送它們。AJAX請求這麼容易被蒙,可着實讓那些計分的在線遊戲開發者們鬱悶的了。(當然,可別那樣騙人家~)

Facebook聊天功能提供了關於AJAX一個有意思的問題案例:把數據從服務器端推送到客戶端。因爲HTTP是一個請求-響應協議,所以聊天服務器不能把新消息發給客戶。取而代之的是客戶端不得不隔幾秒就輪詢下服務器端看自己有沒有新消息。

這些情況發生時長輪詢是個減輕服務器負載挺有趣的技術。如果當被輪詢時服務器沒有新消息,它就不理這個客戶端。而當尚未超時的情況下收到了該客戶的新消息,服務器就會找到未完成的請求,把新消息做爲響應返回給客戶端。


OK,到這裏我們知道了從輸入URL開始後,到請求頁面返回的詳細過程了。你要是能夠達到這種程度,我想面試官會向你投去offer的目光!哈哈。

參考資料:

1.what happens when you type in a URL in browser [closed]
http://stackoverflow.com/questions/2092527/what-happens-when-you-type-in-a-url-in-browser;

2.What is the complete process from entering a url to the browser's address bar to get the rendered page in browser
http://stackoverflow.com/questions/5165310/what-is-the-complete-process-from-entering-a-url-to-the-browsers-address-bar-to;

3.What really happens when you navigate to a URL
http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/;

4. 當你輸入一個網址的時候,實際會發生什麼?
http://www.cnblogs.com/wenanry/archive/2010/02/25/1673368.html;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章