一次HTTP請(qǐng)求的歷程

先宏觀上說(shuō)明一次HTTP請(qǐng)求所經(jīng)歷的七個(gè)步驟

1. 建立TCP連接?

在HTTP工作開(kāi)始之前墓拜,Web瀏覽器首先要通過(guò)網(wǎng)絡(luò)與Web服務(wù)器建立連接渠驼,該連接是通過(guò)TCP來(lái)完成的疫鹊,該協(xié)議與IP協(xié)議共同構(gòu)建Internet杉武,即著名的TCP/IP協(xié)議族儡陨,因此Internet又被稱作是TCP/IP網(wǎng)絡(luò)褪子。HTTP是比TCP更高層次的應(yīng)用層協(xié)議,根據(jù)規(guī)則骗村,只有低層協(xié)議建立之后才能進(jìn)行更高層協(xié)議的連接嫌褪,因此,首先要建立TCP連接胚股,一般TCP連接的端口號(hào)是80笼痛。

2. Web瀏覽器向Web服務(wù)器發(fā)送請(qǐng)求命令??

一旦建立了TCP連接,Web瀏覽器就會(huì)向Web服務(wù)器發(fā)送請(qǐng)求命令。例如:GET/sample/hello.jsp HTTP/1.1缨伊。

3. Web瀏覽器發(fā)送請(qǐng)求頭信息?

?瀏覽器發(fā)送其請(qǐng)求命令之后摘刑,還要以頭信息的形式向Web服務(wù)器發(fā)送一些別的信息,之后瀏覽器發(fā)送了一空白行來(lái)通知服務(wù)器倘核,它已經(jīng)結(jié)束了該頭信息的發(fā)送泣侮。

4. Web服務(wù)器應(yīng)答??

客戶機(jī)向服務(wù)器發(fā)出請(qǐng)求后,服務(wù)器會(huì)客戶機(jī)回送應(yīng)答紧唱, HTTP/1.1 200 OK 活尊,應(yīng)答的第一部分是協(xié)議的版本號(hào)和應(yīng)答狀態(tài)碼。

5. Web服務(wù)器發(fā)送應(yīng)答頭信息??

正如客戶端會(huì)隨同請(qǐng)求發(fā)送關(guān)于自身的信息一樣漏益,服務(wù)器也會(huì)隨同應(yīng)答向用戶發(fā)送關(guān)于它自己的數(shù)據(jù)及被請(qǐng)求的文檔蛹锰。

6. Web服務(wù)器向?yàn)g覽器發(fā)送數(shù)據(jù)??

Web服務(wù)器向?yàn)g覽器發(fā)送頭信息后,它會(huì)發(fā)送一個(gè)空白行來(lái)表示頭信息的發(fā)送到此為結(jié)束绰疤,接著铜犬,它就以Content-Type應(yīng)答頭信息所描述的格式發(fā)送用戶所請(qǐng)求的實(shí)際數(shù)據(jù)。

7. Web服務(wù)器關(guān)閉TCP連接?

?一般情況下轻庆,一旦Web服務(wù)器向?yàn)g覽器發(fā)送了請(qǐng)求數(shù)據(jù)癣猾,它就要關(guān)閉TCP連接,然后如果瀏覽器或者服務(wù)器在其頭信息加入了這行代碼:Connection:keep-aliveTCP連接在發(fā)送后將仍然保持打開(kāi)狀態(tài)余爆,于是纷宇,瀏覽器可以繼續(xù)通過(guò)相同的連接發(fā)送請(qǐng)求。保持連接節(jié)省了為每個(gè)請(qǐng)求建立新連接所需的時(shí)間蛾方,還節(jié)約了網(wǎng)絡(luò)帶寬像捶。

1.準(zhǔn)備

當(dāng)你在瀏覽器中輸入網(wǎng)址(例如www.coder.com)并且敲了回車以后, 瀏覽器首先要做的事情就是獲得coder.com的IP地址桩砰,具體的做法就是發(fā)送一個(gè)UDP的包給DNS服務(wù)器拓春,DNS服務(wù)器會(huì)返回coder.com的IP, 這時(shí)候?yàn)g覽器通常會(huì)把IP地址給緩存起來(lái),這樣下次訪問(wèn)就會(huì)加快亚隅。

比如Chrome硼莽, 你可以通過(guò)chrome://net-internals/#dns來(lái)查看。

有了服務(wù)器的IP煮纵, 瀏覽器就要可以發(fā)起HTTP請(qǐng)求了沉删,但是HTTP Request/Response必須在TCP這個(gè)“虛擬的連接”上來(lái)發(fā)送和接收。

想要建立“虛擬的”TCP連接醉途,TCP郵差需要知道4個(gè)東西:(本機(jī)IP, 本機(jī)端口,服務(wù)器IP, 服務(wù)器端口)砖茸,現(xiàn)在只知道了本機(jī)IP,服務(wù)器IP隘擎, 兩個(gè)端口怎么辦?

本機(jī)端口很簡(jiǎn)單凉夯,操作系統(tǒng)可以給瀏覽器隨機(jī)分配一個(gè)货葬, 服務(wù)器端口更簡(jiǎn)單采幌,用的是一個(gè)“眾所周知”的端口,HTTP服務(wù)就是80震桶, 我們直接告訴TCP郵差就行休傍。

經(jīng)過(guò)三次握手以后,客戶端和服務(wù)器端的TCP連接就建立起來(lái)了蹲姐! 終于可以發(fā)送HTTP請(qǐng)求了磨取。


2.Web服務(wù)器


一個(gè)HTTP GET請(qǐng)求經(jīng)過(guò)千山萬(wàn)水,歷經(jīng)多個(gè)路由器的轉(zhuǎn)發(fā)柴墩,終于到達(dá)服務(wù)器端(HTTP數(shù)據(jù)包可能被下層進(jìn)行分片傳輸忙厌,略去不表)。

Web服務(wù)器需要著手處理了江咳,它有三種方式來(lái)處理:

(1) 可以用一個(gè)線程來(lái)處理所有請(qǐng)求逢净,同一時(shí)刻只能處理一個(gè),這種結(jié)構(gòu)易于實(shí)現(xiàn)歼指,但是這樣會(huì)造成嚴(yán)重的性能問(wèn)題爹土。

(2) 可以為每個(gè)請(qǐng)求分配一個(gè)進(jìn)程/線程,但是當(dāng)連接太多的時(shí)候踩身,服務(wù)器端的進(jìn)程/線程會(huì)耗費(fèi)大量?jī)?nèi)存資源胀茵,進(jìn)程/線程的切換也會(huì)讓CPU不堪重負(fù)。

(3) 復(fù)用I/O的方式惰赋,很多Web服務(wù)器都采用了復(fù)用結(jié)構(gòu)宰掉,例如通過(guò)epoll的方式監(jiān)視所有的連接,當(dāng)連接的狀態(tài)發(fā)生變化(如有數(shù)據(jù)可讀)赁濒, 才用一個(gè)進(jìn)程/線程對(duì)那個(gè)連接進(jìn)行處理轨奄,處理完以后繼續(xù)監(jiān)視,等待下次狀態(tài)變化拒炎。 用這種方式可以用少量的進(jìn)程/線程應(yīng)對(duì)成千上萬(wàn)的連接請(qǐng)求挪拟。

(碼農(nóng)翻身注:詳情參見(jiàn)《Http Server:一個(gè)差生的逆襲》)

我們使用Nginx這個(gè)非常流行的Web服務(wù)器來(lái)繼續(xù)下面的故事。

對(duì)于HTTP GET請(qǐng)求击你,Nginx利用epoll的方式給讀取了出來(lái)玉组, Nginx接下來(lái)要判斷,這是個(gè)靜態(tài)的請(qǐng)求還是個(gè)動(dòng)態(tài)的請(qǐng)求岸≈丁惯雳?

如果是靜態(tài)的請(qǐng)求(HTML文件,JavaScript文件鸿摇,CSS文件石景,圖片等),也許自己就能搞定了(當(dāng)然依賴于Nginx配置,可能轉(zhuǎn)發(fā)到別的緩存服務(wù)器去)潮孽,讀取本機(jī)硬盤(pán)上的相關(guān)文件揪荣,直接返回。

如果是動(dòng)態(tài)的請(qǐng)求往史,需要后端服務(wù)器(如Tomcat)處理以后才能返回仗颈,那就需要向Tomcat轉(zhuǎn)發(fā),如果后端的Tomcat還不止一個(gè)椎例,那就需要按照某種策略選取一個(gè)挨决。

例如Ngnix支持這么幾種:

輪詢:按照次序挨個(gè)向后端服務(wù)器轉(zhuǎn)發(fā)

權(quán)重:給每個(gè)后端服務(wù)器指定一個(gè)權(quán)重,相當(dāng)于向后端服務(wù)器轉(zhuǎn)發(fā)的幾率粟矿。

ip_hash: 根據(jù)ip做一個(gè)hash操作凰棉,然后找個(gè)服務(wù)器轉(zhuǎn)發(fā),這樣的話同一個(gè)客戶端ip總是會(huì)轉(zhuǎn)發(fā)到同一個(gè)后端服務(wù)器陌粹。

fair:根據(jù)后端服務(wù)器的響應(yīng)時(shí)間來(lái)分配請(qǐng)求撒犀,響應(yīng)時(shí)間段的優(yōu)先分配。


不管用哪種算法掏秩,某個(gè)后端服務(wù)器最終被選中或舞,然后Nginx需要把HTTP Request轉(zhuǎn)發(fā)給后端的Tomcat,并且把Tomcat輸出的HttpResponse再轉(zhuǎn)發(fā)給瀏覽器蒙幻。

由此可見(jiàn)映凳,Nginx在這種場(chǎng)景下,是一個(gè)代理人的角色邮破。


3.應(yīng)用服務(wù)器

Http Request終于來(lái)到了Tomcat诈豌,這是一個(gè)由Java寫(xiě)的、可以處理Servlet/JSP的容器抒和,我們的代碼就運(yùn)行在這個(gè)容器之中矫渔。

如同Web服務(wù)器一樣, Tomcat也可能為每個(gè)請(qǐng)求分配一個(gè)線程去處理摧莽,即通常所說(shuō)的BIO模式(Blocking I/O 模式)庙洼。

也可能使用I/O多路復(fù)用技術(shù),僅僅使用若干線程來(lái)處理所有請(qǐng)求镊辕,即NIO模式油够。

不管用哪種方式,Http Request 都會(huì)被交給某個(gè)Servlet處理征懈,這個(gè)Servlet又會(huì)把Http Request做轉(zhuǎn)換石咬,變成框架所使用的參數(shù)格式,然后分發(fā)給某個(gè)Controller(如果你是在用Spring)或者Action(如果你是在Struts)卖哎。

剩下的故事就比較簡(jiǎn)單了(不鬼悠,對(duì)碼農(nóng)來(lái)說(shuō)虏束,其實(shí)是最復(fù)雜的部分),就是執(zhí)行碼農(nóng)經(jīng)常寫(xiě)的增刪改查邏輯厦章,在這個(gè)過(guò)程中很有可能和緩存、數(shù)據(jù)庫(kù)等后端組件打交道照藻,最終返回HTTP Response袜啃,由于細(xì)節(jié)依賴業(yè)務(wù)邏輯,略去不表幸缕。

根據(jù)我們的例子群发,這個(gè)HTTP Response應(yīng)該是一個(gè)HTML頁(yè)面。

4.歸途

Tomcat很高興地把Http Response發(fā)給了Ngnix 发乔。

Ngnix也很高興地把Http Response 發(fā)給了瀏覽器熟妓。


發(fā)完以后TCP連接能關(guān)閉嗎?

如果使用的是HTTP1.1栏尚, 這個(gè)連接默認(rèn)是keep-alive起愈,也就是說(shuō)不能關(guān)閉;

如果是HTTP1.0译仗,要看看之前的HTTP Request Header中有沒(méi)有Connetion:keep-alive抬虽,如果有,那也不能關(guān)閉纵菌。

5.瀏覽器再次工作

瀏覽器收到了Http Response阐污,從其中讀取了HTML頁(yè)面,開(kāi)始準(zhǔn)備顯示這個(gè)頁(yè)面咱圆。

但是這個(gè)HTML頁(yè)面中可能引用了大量其他資源笛辟,例如js文件,CSS文件序苏,圖片等手幢,這些資源也位于服務(wù)器端,并且可能位于另外一個(gè)域名下面杠览,例如static.coder.com弯菊。

瀏覽器沒(méi)有辦法,只好一個(gè)個(gè)地下載踱阿,從使用DNS獲取IP開(kāi)始管钳,之前做過(guò)的事情還要再來(lái)一遍。不同之處在于不會(huì)再有應(yīng)用服務(wù)器如Tomcat的介入了软舌。

如果需要下載的外部資源太多才漆,瀏覽器會(huì)創(chuàng)建多個(gè)TCP連接,并行地去下載佛点。

但是同一時(shí)間對(duì)同一域名下的請(qǐng)求數(shù)量也不能太多醇滥,要不然服務(wù)器訪問(wèn)量太大黎比,受不了。所以瀏覽器要限制一下鸳玩, 例如Chrome在Http1.1下只能并行地下載6個(gè)資源阅虫。


當(dāng)服務(wù)器給瀏覽器發(fā)送JS,CSS這些文件時(shí),會(huì)告訴瀏覽器這些文件什么時(shí)候過(guò)期(使用Cache-Control或者Expire)不跟,瀏覽器可以把文件緩存到本地颓帝,當(dāng)?shù)诙握?qǐng)求同樣的文件時(shí),如果不過(guò)期窝革,直接從本地取就可以了购城。

如果過(guò)期了,瀏覽器就可以詢問(wèn)服務(wù)器端虐译,文件有沒(méi)有修改過(guò)瘪板?(依據(jù)是上一次服務(wù)器發(fā)送的Last-Modified和ETag),如果沒(méi)有修改過(guò)(304 Not Modified)漆诽,還可以使用緩存侮攀。否則的話服務(wù)器就會(huì)被最新的文件發(fā)回到瀏覽器。

當(dāng)然如果你按了Ctrl+F5拴泌,會(huì)強(qiáng)制地發(fā)出GET請(qǐng)求魏身,完全無(wú)視緩存。

注:在Chrome下蚪腐,可以通過(guò) chrome://view-http-cache/ 命令來(lái)查看緩存箭昵。

現(xiàn)在瀏覽器得到了三個(gè)重要的東西:

1.HTML ,瀏覽器把它變成DOM Tree

2. CSS, ?瀏覽器把它變成CSS Rule Tree

3. JavaScript回季, 它可以修改DOM Tree

瀏覽器會(huì)通過(guò)DOM Tree和CSS Rule Tree生成所謂“Render Tree”家制,計(jì)算每個(gè)元素的位置/大小,進(jìn)行布局泡一,然后調(diào)用操作系統(tǒng)的API進(jìn)行繪制颤殴,這是一個(gè)非常復(fù)雜的過(guò)程,略去不表鼻忠。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涵但,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子帖蔓,更是在濱河造成了極大的恐慌矮瘟,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件塑娇,死亡現(xiàn)場(chǎng)離奇詭異澈侠,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)埋酬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)哨啃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烧栋,“玉大人,你說(shuō)我怎么就攤上這事拳球∩笮眨” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵祝峻,是天一觀的道長(zhǎng)邑跪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)呼猪,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任砸琅,我火速辦了婚禮宋距,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘症脂。我一直安慰自己谚赎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布诱篷。 她就那樣靜靜地躺著壶唤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪棕所。 梳的紋絲不亂的頭發(fā)上闸盔,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音琳省,去河邊找鬼迎吵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛针贬,可吹牛的內(nèi)容都是我干的击费。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼桦他,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蔫巩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起快压,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤圆仔,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后嗓节,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體荧缘,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年拦宣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了截粗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片信姓。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绸罗,靈堂內(nèi)的尸體忽然破棺而出意推,到底是詐尸還是另有隱情,我是刑警寧澤珊蟀,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布菊值,位于F島的核電站,受9級(jí)特大地震影響育灸,放射性物質(zhì)發(fā)生泄漏腻窒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一磅崭、第九天 我趴在偏房一處隱蔽的房頂上張望儿子。 院中可真熱鬧,春花似錦砸喻、人聲如沸柔逼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愉适。三九已至,卻和暖如春癣漆,著一層夾襖步出監(jiān)牢的瞬間维咸,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工惠爽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腰湾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓疆股,卻偏偏與公主長(zhǎng)得像费坊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子旬痹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理附井,服務(wù)發(fā)現(xiàn),斷路器两残,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 一永毅、概念(載錄于:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436...
    yuantao123434閱讀 8,354評(píng)論 6 152
  • 1.OkHttp源碼解析(一):OKHttp初階2 OkHttp源碼解析(二):OkHttp連接的"前戲"——HT...
    隔壁老李頭閱讀 20,852評(píng)論 24 176
  • Http協(xié)議詳解 標(biāo)簽(空格分隔): Linux 聲明:本片文章非原創(chuàng),內(nèi)容來(lái)源于博客園作者M(jìn)IN飛翔的HTTP協(xié)...
    Sivin閱讀 5,223評(píng)論 3 82
  • 2017年8月28日 星期一 雨 簡(jiǎn)單的星期一睡到八點(diǎn)多 洗了個(gè)頭化了個(gè)妝 回到我四年前夢(mèng)開(kāi)始的地方 大連市教育學(xué)...
    HelloMondayZs閱讀 157評(píng)論 0 0