輸入網址瀏覽器呈現頁面內容,中間發生了什么?

      網友投稿 869 2022-05-29

      本文轉載自公眾號 碼農翻身

      前言

      這篇文章是應網友之邀所寫,主要描述一下我們訪問網站時, 從輸入網址到最后瀏覽器呈現內容,中間發生了什么。

      之前寫過兩篇文章描述了一個電腦如何通過DHCP、ARP、NAT等上式獲取IP、然后訪問網絡的過程,主要專注在傳輸層和網絡層。

      今天的文章主要專注于應用層,我拿了一個很簡單的網絡結構來講。假定本機已經獲取了IP地址,各種網絡基礎設施已經準備好了。

      由于知識點太多,我肯定會漏掉部分內容,歡迎在留言中補充, 以后我會根據大家建議再寫文章擴展。

      2準備

      當你在瀏覽器中輸入網址(例如www.coder.com)并且敲了回車以后, 瀏覽器首先要做的事情就是獲得coder.com的IP地址,具體的做法就是發送一個UDP的包給DNS服務器,DNS服務器會返回coder.com的IP, 這時候瀏覽器通常會把IP地址給緩存起來,這樣下次訪問就會加快。

      比如Chrome, 你可以通過chrome://net-internals/#dns來查看。

      有了服務器的IP, 瀏覽器就要可以發起HTTP請求了,但是HTTP Request/Response必須在TCP這個“虛擬的連接”上來發送和接收。

      想要建立“虛擬的”TCP連接,TCP郵差需要知道4個東西:(本機IP, 本機端口,服務器IP, 服務器端口),現在只知道了本機IP,服務器IP, 兩個端口怎么辦?

      本機端口很簡單,操作系統可以給瀏覽器隨機分配一個, 服務器端口更簡單,用的是一個“眾所周知”的端口,HTTP服務就是80, 我們直接告訴TCP郵差就行。

      經過三次握手以后,客戶端和服務器端的TCP連接就建立起來了! 終于可以發送HTTP請求了。

      之所以把TCP連接畫成虛線,是因為這個連接是虛擬的, 詳情可參見之前的文章《TCP/IP之大明郵差》,《張大胖的Socket》

      3Web服務器

      一個HTTP GET請求經過千山萬水,歷經多個路由器的轉發,終于到達服務器端(HTTP數據包可能被下層進行分片傳輸,略去不表)。

      Web服務器需要著手處理了,它有三種方式來處理:

      (1) 可以用一個線程來處理所有請求,同一時刻只能處理一個,這種結構易于實現,但是這樣會造成嚴重的性能問題。

      (2) 可以為每個請求分配一個進程/線程,但是當連接太多的時候,服務器端的進程/線程會耗費大量內存資源,進程/線程的切換也會讓CPU不堪重負。

      (3) 復用I/O的方式,很多Web服務器都采用了復用結構,例如通過epoll的方式監視所有的連接,當連接的狀態發生變化(如有數據可讀), 才用一個進程/線程對那個連接進行處理,處理完以后繼續監視,等待下次狀態變化。 用這種方式可以用少量的進程/線程應對成千上萬的連接請求。

      (碼農翻身注:詳情參見《Http Server:一個差生的逆襲》)

      我們使用Nginx這個非常流行的Web服務器來繼續下面的故事。

      對于HTTP GET請求,Nginx利用epoll的方式給讀取了出來, Nginx接下來要判斷,這是個靜態的請求還是個動態的請求啊?

      如果是靜態的請求(HTML文件,JavaScript文件,CSS文件,圖片等),也許自己就能搞定了(當然依賴于Nginx配置,可能轉發到別的緩存服務器去),讀取本機硬盤上的相關文件,直接返回。

      如果是動態的請求,需要后端服務器(如Tomcat)處理以后才能返回,那就需要向Tomcat轉發,如果后端的Tomcat還不止一個,那就需要按照某種策略選取一個。

      例如Ngnix支持這么幾種:

      輪詢:按照次序挨個向后端服務器轉發

      權重:給每個后端服務器指定一個權重,相當于向后端服務器轉發的幾率。

      ip_hash: 根據ip做一個hash操作,然后找個服務器轉發,這樣的話同一個客戶端ip總是會轉發到同一個后端服務器。

      fair:根據后端服務器的響應時間來分配請求,響應時間段的優先分配。

      不管用哪種算法,某個后端服務器最終被選中,然后Nginx需要把HTTP Request轉發給后端的Tomcat,并且把Tomcat輸出的HttpResponse再轉發給瀏覽器。

      由此可見,Nginx在這種場景下,是一個代理人的角色。

      5應用服務器

      Http Request終于來到了Tomcat,這是一個由Java寫的、可以處理Servlet/JSP的容器,我們的代碼就運行在這個容器之中。

      如同Web服務器一樣, Tomcat也可能為每個請求分配一個線程去處理,即通常所說的BIO模式(Blocking I/O 模式)。

      也可能使用I/O多路復用技術,僅僅使用若干線程來處理所有請求,即NIO模式。

      不管用哪種方式,Http Request 都會被交給某個Servlet處理,這個Servlet又會把Http Request做轉換,變成框架所使用的參數格式,然后分發給某個Controller(如果你是在用Spring)或者Action(如果你是在Struts)。

      剩下的故事就比較簡單了(不,對碼農來說,其實是最復雜的部分),就是執行碼農經常寫的增刪改查邏輯,在這個過程中很有可能和緩存、數據庫等后端組件打交道,最終返回HTTP Response,由于細節依賴業務邏輯,略去不表。

      根據我們的例子,這個HTTP Response應該是一個HTML頁面。

      6歸途

      從輸入網址到瀏覽器呈現頁面內容,中間發生了什么?

      Tomcat很高興地把Http Response發給了Ngnix 。

      Ngnix也很高興地把Http Response 發給了瀏覽器。

      發完以后TCP連接能關閉嗎?

      如果使用的是HTTP1.1, 這個連接默認是keep-alive,也就是說不能關閉;

      如果是HTTP1.0,要看看之前的HTTP Request Header中有沒有Connetion:keep-alive,如果有,那也不能關閉。

      7瀏覽器再次工作

      瀏覽器收到了Http Response,從其中讀取了HTML頁面,開始準備顯示這個頁面。

      但是這個HTML頁面中可能引用了大量其他資源,例如js文件,CSS文件,圖片等,這些資源也位于服務器端,并且可能位于另外一個域名下面,例如static.coder.com。

      瀏覽器沒有辦法,只好一個個地下載,從使用DNS獲取IP開始,之前做過的事情還要再來一遍。不同之處在于不會再有應用服務器如Tomcat的介入了。

      如果需要下載的外部資源太多,瀏覽器會創建多個TCP連接,并行地去下載。

      但是同一時間對同一域名下的請求數量也不能太多,要不然服務器訪問量太大,受不了。所以瀏覽器要限制一下, 例如Chrome在Http1.1下只能并行地下載6個資源。

      當服務器給瀏覽器發送JS,CSS這些文件時,會告訴瀏覽器這些文件什么時候過期(使用Cache-Control或者Expire),瀏覽器可以把文件緩存到本地,當第二次請求同樣的文件時,如果不過期,直接從本地取就可以了。

      如果過期了,瀏覽器就可以詢問服務器端,文件有沒有修改過?(依據是上一次服務器發送的Last-Modified和ETag),如果沒有修改過(304 Not Modified),還可以使用緩存。否則的話服務器就會被最新的文件發回到瀏覽器。

      當然如果你按了Ctrl+F5,會強制地發出GET請求,完全無視緩存。

      注:在Chrome下,可以通過 chrome://view-http-cache/ 命令來查看緩存。

      現在瀏覽器得到了三個重要的東西:

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

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

      3. JavaScript, 它可以修改DOM Tree

      瀏覽器會通過DOM Tree和CSS Rule Tree生成所謂“Render Tree”,計算每個元素的位置/大小,進行布局,然后調用操作系統的API進行繪制,這是一個非常復雜的過程,略去不表。

      到目前為止,我們終于在瀏覽器中看到了www.coder.com的內容。

      —————END—————

      喜歡本文的朋友們,歡迎長按下圖關注訂閱號程序員小灰,收看更多精彩內容

      HTTP TCP/IP

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:經典Java面試100例,輕松搞定BAT——高頻面試題(中)
      下一篇:Spring Boot Actuator詳解與深入應用(一):Actuator 1.x
      相關文章
      亚洲乱码中文字幕小综合| 国产亚洲综合久久系列| 亚洲人成人一区二区三区| 亚洲成年看片在线观看| 亚洲乱色熟女一区二区三区蜜臀| 亚洲免费福利视频| 亚洲免费视频网址| 91嫩草亚洲精品| 亚洲第一页在线观看| 亚洲欧洲久久精品| 亚洲人成在线精品| 亚洲va在线va天堂成人| 国内精品久久久久影院亚洲 | 国产亚洲精久久久久久无码77777 国产亚洲精品成人AA片新蒲金 | 亚洲伊人久久大香线蕉结合| 亚洲成AV人片久久| 亚洲一区二区三区不卡在线播放| 亚洲国产成a人v在线| 久久精品国产亚洲AV蜜臀色欲 | 一区国严二区亚洲三区| 亚洲男人的天堂在线va拉文| 精品国产人成亚洲区| 亚洲啪啪综合AV一区| 亚洲AV无码码潮喷在线观看| 亚洲精选在线观看| 亚洲男人天堂影院| 亚洲国产精品综合久久20| 亚洲高清毛片一区二区| 国产成人亚洲午夜电影| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 精品亚洲视频在线观看 | 亚洲熟妇av午夜无码不卡| 亚洲成a人无码亚洲成av无码| 看亚洲a级一级毛片| 亚洲性日韩精品国产一区二区| 在线精品亚洲一区二区三区| 久久香蕉国产线看观看亚洲片| 久久综合亚洲鲁鲁五月天| 亚洲AV成人无码天堂| 国产精品亚洲专区无码牛牛 | 亚洲国产成人99精品激情在线|