百度面試題:從輸入url到顯示網頁,后臺發生了什么?

參考http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/

http://www.cnblogs.com/wenanry/archive/2010/02/25/1673368.html

原文:http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/

作為一個軟件開發者,你一定會對網絡應用如何工作有一個完整的層次化的認知,同樣這里也包括這些應用所用到的技術:像瀏覽器,HTTP,HTML,網絡服務器,需求處理等等。

本文將更深入的研究當你輸入一個網址的時候,后臺到底發生了一件件什么樣的事~

1. 首先嘛,你得在瀏覽器里輸入要網址:

image

2. 瀏覽器查找域名的IP地址

image

導航的第一步是通過訪問的域名找出其IP地址。DNS查找過程如下:

  • 瀏覽器緩存 – 瀏覽器會緩存DNS記錄一段時間。 有趣的是,操作系統沒有告訴瀏覽器儲存DNS記錄的時間,這樣不同瀏覽器會儲存個自固定的一個時間(2分鐘到30分鐘不等)。
  • 系統緩存 – 如果在瀏覽器緩存里沒有找到需要的記錄,瀏覽器會做一個系統調用(windows里是gethostbyname)。這樣便可獲得系統緩存中的記錄。
  • 路由器緩存 – 接著,前面的查詢請求發向路由器,它一般會有自己的DNS緩存。
  • ISP DNS 緩存 – 接下來要check的就是ISP緩存DNS的服務器。在這一般都能找到相應的緩存記錄。
  • 遞歸搜索 – 你的ISP的DNS服務器從跟域名服務器開始進行遞歸搜索,從.com頂級域名服務器到Facebook的域名服務器。一般DNS服務器的緩存中會有.com域名服務器中的域名,所以到頂級服務器的匹配過程不是那么必要了。

DNS遞歸查找如下圖所示:

500px-An_example_of_theoretical_DNS_recursion_svg

DNS有一點令人擔憂,這就是像wikipedia.org 或者 facebook.com這樣的整個域名看上去只是對應一個單獨的IP地址。還好,有幾種方法可以消除這個瓶頸:

  • 循環 DNS 是DNS查找時返回多個IP時的解決方案。舉例來說,Facebook.com實際上就對應了四個IP地址。
  • 負載平衡器 是以一個特定IP地址進行偵聽并將網絡請求轉發到集群服務器上的硬件設備。 一些大型的站點一般都會使用這種昂貴的高性能負載平衡器。
  • 地理 DNS 根據用戶所處的地理位置,通過把域名映射到多個不同的IP地址提高可擴展性。這樣不同的服務器不能夠更新同步狀態,但映射靜態內容的話非常好。
  • Anycast 是一個IP地址映射多個物理主機的路由技術。 美中不足,Anycast與TCP協議適應的不是很好,所以很少應用在那些方案中。

大多數DNS服務器使用Anycast來獲得高效低延遲的DNS查找。

3. 瀏覽器給web服務器發送一個HTTP請求

image

因為像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 and 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. 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. 瀏覽器跟蹤重定向地址

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. 服務器“處理”請求

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. 服務器發回一個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. 瀏覽器開始顯示HTML

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

image

9. 瀏覽器發送獲取嵌入在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. 瀏覽器發送異步(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是一個請求-響應協議,所以聊天服務器不能把新消息發給客戶。取而代之的是客戶端不得不隔幾秒就輪詢下服務器端看自己有沒有新消息。

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

總結一下

希望看了本文,你能明白不同的網絡模塊是如何協同工作的

轉載于:https://www.cnblogs.com/rollenholt/archive/2012/03/23/2414345.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379862.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379862.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379862.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

VS2005無法啟動修復辦法

c:\Program Files\Microsoft Visual Studio 8\Common7\IDE>devenv /ResetSkipPkgs 轉載于:https://www.cnblogs.com/doc/archive/2008/10/10/1307887.html

Java——設計模式(工廠方法模式)

* A:工廠方法模式概述* 工廠方法模式中抽象工廠類負責定義創建對象的接口&#xff0c;具體對象的創建工作由繼承抽象工廠的具體類實現。* 簡單來說&#xff1a;先定義一個工廠&#xff0c;工廠里面有些方法&#xff0c;這些方法就是用來創建動物的&#xff0c;然后有很多子工…

python安全攻防---爬蟲基礎---get和post提交數據

get提交數據1 get提交的數據就附在提交給服務器的url之后&#xff0c;以&#xff1f;開頭參數之間以&隔開&#xff0c;例如/admin/user/123456.aspx?name123&id123 案例&#xff1a;寫個腳本&#xff0c;在sogou自動搜索周杰倫&#xff0c;并將搜索頁面的數據獲取 程…

JavaMail中解決中文附件名亂碼的問題

網上有很多類似的解決方案&#xff0c;很多是使用 if ((fileName ! null) && (fileName.toLowerCase().indexOf("gb2312") ! -1)){ fileName MimeUtility.decodeText(fileName); } 來解決&#xff0c;但對應gbk編碼的附件名&#xff0c;這里仍不能正確處…

Java ObjectOutputStream writeBytes()方法與示例

ObjectOutputStream類writeBytes()方法 (ObjectOutputStream Class writeBytes() method) writeBytes() method is available in java.io package. writeBytes()方法在java.io包中可用。 writeBytes() method is used to write the given string as a sequence of bytes. write…

如何集中注意力(3)

如何集中注意力&#xff08;3&#xff09; [ 2008-10-20 10:15 ]by Glen Stansberry of LifeDev (feed). 集中注意力并不是一件很容易的事情&#xff0c;尤其是處在當前這個充滿誘惑和紛擾的世界里。下面是繼續告訴大家一些有幫助的方法&#xff1a; 7. Plan your day to the T…

Java——網絡編程三要素

* A:計算機網絡* 是指將地理位置不同的具有獨立功能的多臺計算機及其外部設備&#xff0c;通過通信線路連接起來&#xff0c;在網絡操作系統、網絡管理軟件及網絡通信協議的管理和協調下&#xff0c;實現資源共享和信息傳遞的計算機系統。* 其實我們這些網&#xff0c;之所以能…

python安全攻防---爬蟲基礎--re解析數據

0x01 re基礎 使用re模塊&#xff0c;必須先導入re模塊 import refindall()&#xff1a;匹配所有符合正則的內容&#xff0c;返回的是一個列表 import restr "我的電話&#xff1a;10086&#xff0c;女朋友電話&#xff1a;11011" list re.findall(\d,str) print…

BSP for good 3d engine

1.open sourcehttp://irrlicht.sourceforge.net/downloads/ 2.不錯的小材質http://www.permadi.com/tutorial/webgraph/index.html 3.java bsp display(demo):http://www.symbolcraft.com/graphics/bsp/index.php http://www.faqs.org/faqs/graphics/bsptree-faq/ 4.a bps ill…

Java InputStreamReader getEncoding()方法及示例

InputStreamReader類的getEncoding()方法 (InputStreamReader Class getEncoding() method) getEncoding() method is available in java.io package. getEncoding()方法在java.io包中可用。 getEncoding() method is used to get the encoding name avail for this InputStrea…

python安全攻防---爬蟲基礎---BeautifulSoup解析

0x01 基礎 使用bs4首先要安裝&#xff0c;安裝后導入 import bs4bs對象有兩個方法&#xff0c;一個是find&#xff0c;另一個是find_all find&#xff08;標簽名&#xff0c;屬性值&#xff09;&#xff1a;只返回一個&#xff0c;返回也是bs對象&#xff0c;可以繼續用find…

DataRabbit 3.1發布,完全支持SqlServer2005/2008

增加了對SqlServer2005/2008的新的數據類型的支持&#xff0c;如uniqueidentifier、time、sql_variant等。另外&#xff0c;EntityCreator也一起更新--不再強迫為Entity生成ToString&#xff08;&#xff09;方法&#xff0c;使用者可以主動選擇是否要生成。 DataRabbit 3.1 下…

Java——Socket通信原理

* Socket通信原理圖解* A:Socket(中文翻譯為&#xff1a;電源插座)套接字概述* 網絡上具有唯一標識的IP地址和端口號組合在一起才能構成唯一能識別的標識套接字* 通信的兩端都有Socket(兩端都是電源插座&#xff0c;中間是啥&#xff1f;不就是電線啦&#xff0c;電…

asp.net鏈接mysql數據庫------------【個人收集】

在web.config文件中添加如下樣式的數據庫鏈接字符串&#xff1a; <add name"dbconnection" connectionString"DataBasedatabasename;Server127.0.0.1;Uid用戶名;Pwd密碼;character setgbk;" providerName"MySql.Data.MySqlClient"/></c…

sql2005 遠程連接

SQL Server 2005 不允許遠程連接解決方法轉載于:https://www.cnblogs.com/lcq135/archive/2008/11/06/1328380.html

Java GregorianCalendar computeTime()方法與示例

GregorianCalendar類computeTime()方法 (GregorianCalendar Class computeTime() method) computeTime() method is available in java.util package. java.util包中提供了computeTime()方法 。 computeTime() method is used to compute the calendar fields to the calendar …

python安全攻防---scapy基礎---計算機網絡各層協議

網絡層次劃分 比較常用的是TCP/IP五層協議。 0x01應用層 應用層是網絡應用程序以及它們的應用層協議存留的地方。應用層協議和應用程序直接掛鉤 DHCP(Dynamic Host Configuration Protocol)動態主機分配協議&#xff0c;使用 UDP 協議工作&#xff0c;主要有兩個用途&#xf…

一點心得(0)

1, 在C中&#xff0c;如果棧里的空間不足的話&#xff0c;要考慮用new命令在堆上動態生成數據&#xff0c;比如說保存所有無符號整數型的bitset&#xff0c;得用bitset<UINT_MAX1>* bs new bitset<UINT_MAX1>;來聲明定義&#xff0c;最后別忘了delete掉。 2, make…

Java——UPD輸出及優化再優化

* UPD傳輸不區分客戶端跟服務端&#xff0c;* 這里用Send和Receive這兩個方法決定誰發誰收 * 1.發送Send * 創建DatagramSocket,隨機端口號* 創建DatagramPacket,指定數據、長度、地址、端口* 創建DatagramSocket發送DatagramPacket* 關閉DatagramSocket 代碼如下&…

FLEX:圖形制作皮膚vs編程制作皮膚

Styles&#xff08;樣式&#xff09;提供了一個可以自定義flex外觀的層.可以圖形制作皮膚&#xff0c;也可以編程實現. &#xff08;小小菜鳥翻譯&#xff09; 圖形制作皮膚的 優點是 很容易實現&#xff0c;通過位圖&#xff0c;矢量圖&#xff0c;swf。 缺點是功能有限。…