從輸入URL到頁面展示,這中間發生了什麼

前端技術驛站 2021-09-19 12:22:47 阅读数:667

url 展示 生了

"從瀏覽器地址欄輸入 url 到請求返回發生了什麼?",呃,這道面試題我都不知道被問了多少遍,作為必考題,我們有必要總結一下。

總的來說,分為以下幾個過程:

  • 1、DNS 解析
  • 2、TCP 連接
  • 3、發送 HTTP 請求
  • 4、服務器處理請求並返回 HTTP 報文
  • 5、瀏覽器解析渲染頁面

下面讓我們了解下這 5 個過程。

一、DNS 解析

DNS( Domain Name System)是"域名系統"的英文縮寫。DNS 解析的過程就是尋找哪臺機器上有你需要資源的過程。

當你在瀏覽器中輸入一個地址時,例如www.shanzhonglei.com,其實不是網站真正意義上的地址。互聯網上每一臺計算機的唯一標識是它的 IP 地址,但是 IP 地址並不方便記憶,所以就用網址代替 IP 地址。

DNS 域名解析過程

  • 1、瀏覽器緩存。首先會檢查瀏覽器緩存中有沒有域名對應的 ip 地址,這個緩存是有過期時長的,一般是幾分鐘到幾小時不等。
  • 2、本地 hosts 文件。檢查自己本地的 hosts 文件是否有這個網址映射關系。windows 就是 C:\Windows\System32\drivers\etc\hosts 文件,linux 在/etc/hosts 文件中配置。
  • 3、路由器緩存。可能還存在路由器緩存這一層。
  • 3、本地 DNS 服務器。如果要查詢的域名,包含在本地配置區域資源中,則返回解析結果給客戶機。此解析具有權威性。
  • 4、根 DNS 服務器。如果未用轉發模式,本地 DNS 就把請求發至 13 臺根 DNS 進行解析。如果是轉發模式,DNS 服務器就會把請求轉發至上一級 DNS 服務器,由上一級服務器進行解析,上一級服務器如果不能解析,或找根 DNS 或把轉請求轉至上上級,以此循環。
  • 5、此外還會去查詢頂級域名服務器和主域名服務器

所以解析過程大概為:瀏覽器緩存->本地hosts文件->路由器緩存->本地DNS服務器->根DNS服務器->頂級域名服務器->主域名服務器

前端 DNS 優化

可以在 html 頁面頭部寫入 dns 緩存地址。

<meta http-equiv="x-dns-prefetch-control" content="on" />
<link rel="dns-prefetch" href="http://www.shanzhonglei.com/" />

DNS 負載均衡

如果 DNS 返回的 IP 地址每次都一樣,那麼這臺機器需要多高的性能和儲存才能滿足億萬請求呢?

其實 DNS 可以返回一個合適的機器的 IP 給用戶,例如可以根據每臺機器的負載量,該機器離用戶地理比特置的距離等等,這種過程就是 DNS 負載均衡,又叫做 DNS 重定向。

大家耳熟能詳的 CDN(Content Delivery Network)就是利用 DNS 的重定向技術,DNS 服務器會返回一個跟用戶最接近的點的 IP 地址給用戶,CDN 節點的服務器負責響應用戶的請求,提供所需的內容。

二、TCP 連接

用戶數據包協議(User Datagram Protocol),簡稱 UDP,是基於 IP 之上開發能和應用打交道的協議。

UDP 中一個最重要的信息是端口號,端口號其實就是一個數字,每個想訪問網絡的程序都需要綁定一個端口號。

通過端口號 UDP 就能把指定的數據包發送給指定的程序了,所以通過 IP 地址信息把數據包發送給指定的電腦,而 UDP 通過端口號把數據包分發給正確的程序。

TCP(Transmission Control Protocol,傳輸控制協議)是一種面向連接的、可靠的、基於字節流的傳輸層通信協議。TCP 相對於 UDP 有兩個特點:

  • 對於數據包的丟失,建立重傳機制
  • TCP 引入數據包排序機制,用來保證把亂序的數據包組合成一個完整的文件

三次握手,就是指在建立一個 TCP 連接時,客戶端和服務器總共要發送 3 個數據包來確認連接的建立。三次握手主要作用:

  • 1、確認雙方的接收能力和發送能力
  • 2、指定自己的初始化序列號,為後面的可靠性做准備

2.1 三次握手過程

剛開始客戶端處於 Closed 的狀態,服務器處於 Listen 狀態。

  1. 客戶端發送到服務器。客戶端發送 SYN 報文給服務器,並且指明客戶端初始化序列號為 ISN(c),即以 SYN=1, seq=x 的形式發送過去。此時客戶端處於 SYN_SEND 狀態。
  2. 服務器發送給客戶端。服務器收到客戶端的 SYNISN(c),也發送一個 SYN 回去,同時設置 ACK = ISN(c) + 1 以及指明服務器初始化序列號為 ISN(s),即以 SYN=1, ACK=x+1, seq=y 的形式發送給客戶端。
  3. 客戶端發送到服務器。客戶端收到服務器發送的消息後,設置 ACK = ISN(s) + 1,將自身的 ISN(c) + 1,即以 ACK=y+1, seq=x+1 的形式發送給服務器。此時客戶端處於 ESTABLISHED 階段,服務器收到報文,也處於 ESTABLISHED 階段,雙方建立了連接。

2.2、兩次握手不行嗎?

三次握手的目的:

  1. 客戶端發送數據給服務器,服務器確認自己可以接受客戶端的請求。
  2. 服務器發送數據給客戶端,客戶端確認自己可以發送數據給服務器,也可以接受到服務器的請求。
  3. 客戶端發送數據給服務器,服務器確認自己可以發送數據給客戶端。

如果采用兩次握手,客戶端發送數據給服務器,服務器確認後就當連接開始:

  1. 客戶端發送一次請求給服務器,指定時間後沒響應再發了一個
  2. 服務器先接收到後一個建立連接的請求,然後前一個建立連接的請求,因為網絡延遲等問題,在第二個之後達到了
  3. 服務器認為第二個請求是最新發的,於是向客戶端發送確認報文段,同意建立連接,於是連接建立了(兩次握手)
  4. 這時候客戶端還在等待最新的請求連接(第二次請求),自動忽略服務器發送的關於第一個請求連接的響應,也不發送數據
  5. 服務器一直等待客戶端發送數據,服務器資源被占用

2.3 三次握手過程中可以攜帶數據嗎?

第三次握手的時候可以攜帶,第一第二次不可以攜帶。

第三次握手的時候,客戶端處於 ESTABLISHED 狀態了,它可以建立連接並且知道服務器的接收、發送能力是正常的,所以可以攜帶數據了。

2.3、四次揮手過程

  • 客戶端發送給服務器。客戶端以 FIN=1, seq=u 的形式發送給服務器,錶示需要關閉客戶端和服務器的數據傳輸。此時客戶端處於 FIN_WAIT 狀態。
  • 服務器發送給客戶端。服務器收到信息,先返回 ACK 給客戶端,即以 ACK=1, seq=v, ack=u+1 的形式返回給客戶端,錶示收到客戶端報文了。此時服務器處於 CLOST_WAIT 狀態。
  • 服務器發送給客戶端。服務器等待一會,看客戶端還有沒有數據沒發過來,等處理完這些數據之後,也想斷開連接了,於是發送 FIN 給客戶端,即以 FIN=1, ACK=1, seq=w, ack=u+1 的形式發送給客戶端。此時服務器處於 LAST_ACK 狀態。
  • 客戶端發送給服務器。客戶端收到 FIN 之後,返回 ACK 報文作為應答,即以 ACK=1, seq=w+1 的形式發送給服務器。此時客戶端處於 TIME_WAIT 狀態。

2.4、為什麼需要四次揮手

因為服務器接收到客戶端的關閉請求之後。

如果有一些數據因為網絡延遲等問題沒有發送到,那麼它直接關閉會導致這些數據沒有接收到;亦或者服務器也有一些數據要發送給客戶端,要確保這些數據發送完。

我們知道 TCP 是個可靠的棒小夥,所以它才會第一次回複客戶端收到關閉連接的請求了,第二次回複客戶端你發送的數據應該沒延遲了,我也發送完我要發送的數據了,可以關閉了。

最後客戶端接收到了,回複告訴服務器它也可以關閉了,然後過一陣子確保服務器接收到它發的 ACK 報文之後,也處於 CLOSED 狀態了。這樣就確保了連接的正常關閉。

三、發送 HTTP 請求

發送 HTTP 請求的過程就是構建 HTTP 請求報文,並通過 TCP 協議發送到服務器指定端口(HTTP 協議默認端口 80/8080,HTTPS 協議默認端口 443)。

HTTP 請求報文由 3 部分組成:請求行、請求報文 和 請求正文。

  • 請求行:常用方法有:GET、POST、PUT、DELETE、OPTIONS、HEAD。
  • 請求報頭:允許客戶端向服務器傳遞請求的附加信息和客戶端自身的信息。
  • 請求正文:通過 POST、PUT 等方法時,通常需要客戶端向服務器傳遞數據,這些數據就儲存在請求正文中。

注意,如果本地緩存是否緩存了該資源,就會直接渲染頁面。

GET 和 POST 方法到底有什麼區別?

如果沒有前提,也就是不用任何規範限制的話,我們只考慮語法來說,GET 請求和 POST 請求都能拉取數據。這兩個方式是沒有任何區別的,只有名字不一樣。

RFC 是一種網絡規範,如果基於 RFC 規範,那就不一樣:

  • 1、GET 的數據在 URL 中對所有人都是可見的。POST 的數據不會顯示在 URL 中。
  • 2、GET 對數據長度有限制,當發送數據時,GET 方法向 URL 添加數據;URL 的長度是受限制的(URL 的最大長度是 2048 個字符)。POST 無限制。
  • 3、GET 可收藏為書簽,POST 不可收藏為書簽。
  • 4、GET 後退按鈕/刷新無影響,POST 數據會被重新提交。
  • 5、GET 編碼類型 application/x-www-form-url,POST 編碼類型 encodedapplication/x-www-form-urlencoded 或 multipart/form-data。為二進制數據使用多重編碼。
  • 6、GET 曆史參數會保留在瀏覽器曆史中。POST 參數不會保存在瀏覽器曆史中。
  • 7、GET 只允許 ASCII 字符。POST 沒有限制。也允許二進制數據。
  • 8、與 POST 相比,GET 的安全性較差,因為所發送的數據是 URL 的一部分。在發送密碼或其他敏感信息時絕不要使用 GET !POST 比 GET 更安全,因為參數不會被保存在瀏覽器曆史或 web 服務器日志中。
  • 9、比如 GET 請求只會有一次 TCP 連接,而 POST 請求會有兩次 TCP 連接。對於 GET 方式的請求,瀏覽器會把 http header 和 data 一並發送出去,服務器響應 200(返回數據);而對於 POST,瀏覽器先發送 header,服務器響應 100 continue,瀏覽器再發送 data,服務器響應 200 ok(返回數據)。

四種常見的 POST 提交數據方式:

  • 1.application/x-www-form-urlencoded(錶單默認方式)
  • 2.multipart/form-data(錶單上傳文件)
  • 3.application/json
  • 4.text/xml

四、服務器處理請求並返回 HTTP 報文

這一步,會檢查狀態碼,如果是 301/302,則需要重定向,從 Location 自動中讀取地址,重新發起請求。如果是 200 狀態碼,檢查響應類型 Content-Type,如果是字節流類型,則將該請求提交給下載管理器,該導航流程結束,不再進行後續的渲染。

如果是 html 則通知瀏覽器進程准備渲染進程准備進行渲染。

HTTP 響應報文也是由 3 部分組成:狀態碼、響應報頭 和 響應報文。

  • 狀態碼:
    1xx:指示信息–錶示請求已接收,繼續處理。
    2xx:成功–錶示請求已被成功接收、理解、接受。
    3xx:重定向–要完成請求必須進行更進一步的操作。
    4xx:客戶端錯誤–請求有語法錯誤或請求無法實現。
    5xx:服務器端錯誤–服務器未能實現合法的請求。

平時遇到比較常見的狀態碼有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500(分別錶示什麼請自行查找)。

  • 響應報頭:常見的響應報頭字段 Server、Connection 等。
  • 響應報文:服務器返回給瀏覽器的文本信息,通常 HTML、CSS、JS、圖片等文件就放在這一部分。

狀態碼 301 和 302 的區別?

301 重定向是一種永久重定向,而 302 跳轉是暫時的跳轉。

五、瀏覽器解析渲染頁面

瀏覽器的渲染過程為:

  1. 解析 HTML,生成 DOM
  2. 解析 CSS,生成 CSS 規則樹(CSS Rule Tree)
  3. DOM TreeCSS Rule Tree 相結合,生成 渲染樹Render Tree
  4. 從根節點開始,計算每一個元素的大小、比特置,給出每個節點所應該出現的屏幕精確坐標,從而得到基於渲染樹的 布局渲染樹Layout of the render tree)。
  5. 遍曆渲染樹,將每個節點用 UI 渲染引擎來繪制,從而將整棵樹繪制到頁面上,這個步驟叫 繪制渲染樹Painting the render tree

瀏覽器在解析過程中,如果遇到請求外部資源時,如圖像,JS 等,還會重新執行網絡請求。這個請求過程是异步的,並不會影響 HTML 文檔進行加載,但是當文檔加載過程中遇到 JS 文件,HTML 文檔會掛起渲染過程,不僅要等到文檔中 JS 文件加載完畢還要等待解析執行完畢,才會繼續 HTML 的渲染過程。原因是因為 JS 有可能修改 DOM 結構,這就是 JS 阻塞後續資源下載的根本原因。

CSS 文件的加載不影響 JS 文件的加載,但是卻影響 JS 文件的執行。JS 代碼執行前瀏覽器必須保證 CSS 文件已經下載並加載完畢。

建議將 script 標簽放到 body 標簽底部,或者給 script 標簽添加 defer/async 屬性。

頁面渲染層優化

  • 1、HTML 文檔結構層次盡量少,最好不深於六層
  • 2、脚本盡量後放
  • 3、少量首屏樣式內聯放在標簽內
  • 4、樣式結構層次盡量簡單
  • 5、在脚本中盡量减少 DOM 操作,盡量緩存訪問 DOM 的樣式信息,避免過度觸發回流
  • 6、减少通過 JavaScript 代碼修改元素樣式,盡量使用修改 class 名方式操作樣式或動畫
  • 7、動畫盡量使用在絕對定比特或固定定比特的元素上

擴展

DNS 域名稱和組織類型

DNS 域名稱 組織類型
com 商業公司
edu 教育機構
net 網絡公司
gov 非軍事政府機構
Mil 軍事政府機構

TCP 和 UDP 的區別

  • TCP 是面向連接的,UDP 是無連接的即發送數據前不需要先建立鏈接。
  • TCP 提供可靠的服務。通過 TCP 連接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP 盡最大努力交付,即不保證可靠交付。並且因為 TCP 可靠,面向連接,不會丟失數據因此適合大數據量的交換。
  • TCP 只能是 1 對 1 的,UDP 支持 1 對 1,1 對多。
  • TCP 是面向連接的可靠性傳輸,而 UDP 是不可靠的。

感謝

謝謝閱讀,如有幫助請點個關注、收藏吧

歡迎關注前端技術驛站公眾號,分享學習資料,技術總結!

版权声明:本文为[前端技術驛站]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210919122246724g.html