從URL到看到網頁的過程

来源:https://www.cnblogs.com/Javame/archive/2019/01/10/10247849.html
-Advertisement-
Play Games

從我們輸入URL並按下回車鍵到看到網頁結果之間發生了什麼?換句話說,一張網頁,要經歷怎樣的過程,才能抵達用戶面前?下麵來從一些細節上面嘗試一下探尋裡面的秘密。 前言:鍵盤與硬體中斷 說到輸入URL,當然是從手敲鍵盤開始。對於鍵盤,生活中用到的最常見的鍵盤有兩種:薄膜鍵盤、機械鍵盤。 薄膜鍵盤:由面板 ...


從我們輸入URL並按下回車鍵到看到網頁結果之間發生了什麼?換句話說,一張網頁,要經歷怎樣的過程,才能抵達用戶面前?下麵來從一些細節上面嘗試一下探尋裡面的秘密。

前言:鍵盤與硬體中斷

說到輸入URL,當然是從手敲鍵盤開始。對於鍵盤,生活中用到的最常見的鍵盤有兩種:薄膜鍵盤、機械鍵盤。

  • 薄膜鍵盤:由面板、上電路、隔離層、下電路構成。有外觀優美、壽命較長、成本低廉的特點,是最為流行的鍵盤種類。鍵盤中有一整張雙層膠膜,通過膠膜提供按鍵的回彈力,利用薄膜被按下時按鍵處碳心於線路的接觸來控制按鍵觸發。

  • 機械鍵盤:由鍵帽、機械軸組成。鍵盤打擊感較強,常見於游戲發燒友與打字愛好者。每一個按鍵都有一個獨立的機械觸點開關,利用柱型彈簧提供按鍵的回彈力,用金屬接觸觸點來控制按鍵的觸發。

鍵盤傳輸信號到操作系統後便會觸發硬體中斷處理程式。硬體中斷是操作系統中提高系統效率、滿足實時需求的非常重要的信號處理機制,它是一個非同步信號,並提供相關中斷的註冊表(IDT)與請求線(IRQ)。鍵盤被按壓時,將通過請求線將信號輸入給操作系統,CPU在當前指令結束之後,根據註冊表與信號響應該中斷並利用段寄存器裝入中斷程式入口地址。具體可參看操作系統與彙編相關書籍。

當然本文主要不是介紹硬體與操作系統中的細節,前言只是想說明,從輸入URL到瀏覽器展現結果頁面之間有太多底層相關的知識,懷著一顆敬畏的心並且在有限的篇幅中是無法詳細闡述的,所以本文會將關註點放在在一個稍高的角度上來看,從瀏覽器替我們發送請求之後到看到頁面顯示完成這中間中發生了什麼事情,比如DNS解析、瀏覽器渲染。

瀏覽器解析URL

按下回車鍵之前

比如我按下一個‘b’鍵,會出現很多待選URL給我,第一個便是百度。那麼其實是在瀏覽器接收到這個消息之後,會觸發瀏覽器的自動完成機制,會在你之前訪問過的搜索最匹配的相關URL,會根據特定的演算法顯示出來供用戶選擇。

按下回車鍵之後

依據上述鍵盤觸發原理,一個專用於回車鍵的電流迴路通過不同的方式閉合了。然後觸發硬體中斷,隨之操作系統內核去處理對應中斷。省略其中的過程,最後交給了瀏覽器這樣一個“回車”信號。那麼瀏覽器(本文涉及到的瀏覽器版本都為Chrome 61)會進行以下但不僅限於以下炫酷(亂七八糟)的步驟:

  1. 解析URL:您輸入的是http還是https開頭的網路資源 / file開頭的文件資源 / 待搜索的關鍵字?然後瀏覽器進行對應的資源載入進程

  2. URL轉碼:RFC標準中規定部分字元可以不經過轉碼直接用於URL,但是漢字不在範圍內。所以如果在網址路徑中包含漢字將會被轉碼

  1. HSTS:鑒於HTTPS遺留的安全隱患,大部分現代瀏覽器已經支持HSTS。對於瀏覽器來說,瀏覽器會檢測是否該網路資源存在於預設定的只使用HTTPS的網站列表,或者是否保存過以前訪問過的只能使用HTTPS的網站記錄,如果是,瀏覽器將強行使用HTTPS方式訪問該網站。

DNS解析

不查DNS,讀取緩存

  • 瀏覽器中的緩存:對於Chrome,緩存查看地址為:chrome://net-internals/#dns

  • 本地hosts文件:以Mac與Linux為例,hosts文件所在路徑為:/etc/hosts。所以有一種FQ的方式就是修改hosts文件避免GFW對DNS解析的干擾,直接訪問真正IP地址,但已經不能完全生效因為GFW還有根據IP過濾的機制。

發送DNS查找請求

DNS的查詢方式是:按根功能變數名稱->頂級功能變數名稱->次級功能變數名稱->主機名這樣的方式來查找的,對於某個URL,如下所示

123
主機名.次級功能變數名稱.頂級功能變數名稱.根功能變數名稱--------------------------host.sld.tld.root

查詢步驟為:

  1. 查詢本地DNS伺服器。本地DNS伺服器地址為連接網路時路由器指定的DNS地址,一般為DHCP自動分配的路由器地址,保存在/etc/resolv.conf,而路由器的DNS轉發器將請求轉發到上層ISP的DNS,所以此處本地DNS伺服器是區域網或者運營商的。

  2. 從"根功能變數名稱伺服器"查到"頂級功能變數名稱伺服器"的NS記錄和A記錄(IP地址)。世界上一共有十三組根功能變數名稱伺服器,從A.ROOT-SERVERS.NET一直到M.ROOT-SERVERS.NET,由於已經將這些根功能變數名稱伺服器的IP地址存放在本地DNS伺服器中。

  3. 從"頂級功能變數名稱伺服器"查到"次級功能變數名稱伺服器"的NS記錄和A記錄(IP地址)

  4. 從"次級功能變數名稱伺服器"查出"主機名"的IP地址

以www.google.com為例,下麵是一整個DNS查詢過程:

  1. 由於本次測試是在阿裡雲上的實例進行測試,所以首先從100.100.2.138這個阿裡內網DNS伺服器查找到所有根功能變數名稱伺服器的映射關係。

  2. 訪問根功能變數名稱伺服器(f.root-servers.net),拿到com頂級功能變數名稱伺服器的NS記錄與IP地址。

  3. 訪問頂級功能變數名稱伺服器(e.gtld-servers.net),拿到google.com次級功能變數名稱伺服器的NS記錄與IP地址。

  4. 訪問次級功能變數名稱伺服器(ns2.google.com),拿到www.google.com的IP地址

12345678910111213141516171819202122232425262728293031323334353637383940
➜ dig +trace www.google.com.         388687  IN  NS  m.root-servers.net..         388687  IN  NS  d.root-servers.net..         388687  IN  NS  h.root-servers.net..         388687  IN  NS  l.root-servers.net..         388687  IN  NS  c.root-servers.net..         388687  IN  NS  g.root-servers.net..         388687  IN  NS  a.root-servers.net..         388687  IN  NS  k.root-servers.net..         388687  IN  NS  i.root-servers.net..         388687  IN  NS  e.root-servers.net..         388687  IN  NS  f.root-servers.net..         388687  IN  NS  j.root-servers.net..         388687  IN  NS  b.root-servers.net.;; Received 1097 bytes from 100.100.2.138#53(100.100.2.138) in 1072 mscom.          172800  IN  NS  l.gtld-servers.net.com.          172800  IN  NS  a.gtld-servers.net.com.          172800  IN  NS  i.gtld-servers.net.com.          172800  IN  NS  j.gtld-servers.net.com.          172800  IN  NS  b.gtld-servers.net.com.          172800  IN  NS  f.gtld-servers.net.com.          172800  IN  NS  m.gtld-servers.net.com.          172800  IN  NS  h.gtld-servers.net.com.          172800  IN  NS  e.gtld-servers.net.com.          172800  IN  NS  g.gtld-servers.net.com.          172800  IN  NS  c.gtld-servers.net.com.          172800  IN  NS  k.gtld-servers.net.com.          172800  IN  NS  d.gtld-servers.net.;; Received 1174 bytes from 192.5.5.241#53(f.root-servers.net) in 1841 msgoogle.com.       172800  IN  NS  ns2.google.com.google.com.       172800  IN  NS  ns1.google.com.google.com.       172800  IN  NS  ns3.google.com.google.com.       172800  IN  NS  ns4.google.com.;; Received 664 bytes from 192.12.94.30#53(e.gtld-servers.net) in 185 mswww.google.com.       300 IN  A   216.58.200.228;; Received 48 bytes from 216.239.34.10#53(ns2.google.com) in 2 ms

所以總的來說,DNS的解析是一個逐步縮小範圍的查找過程。

建立HTTPS、TCP連接

確定發送目標

拿到IP之後,還需要拿到那台伺服器的MAC地址才行,在乙太網協議中規定,同一區域網中的一臺主機要和另一臺主機進行直接通信,必須要知道目標主機的MAC地址。所以根據ARP(根據IP地址獲取物理地址的一個TCP/IP協議)獲取到MAC地址之後保存到本地ARP緩存之後與目標主機準備開始通信。具體細節參見維基百科DHCH/ARP。

建立TCP連接

為什麼握手一定要是三次?

 

  • 第一次與第二次握手完成意味著:A能發送請求到B,並且B能解析A的請求

  • 第二次與第三次握手完成意味著:A能解析B的請求,並且B能發送請求到A

這樣就保證了A與B之間既能相互發送請求也能相互接收解析請求。同時避免了因為網路延遲產生的重覆連接問題,比如A發送一次連接請求但網路延遲導致這次請求是在A重發連接請求並完成與B通信之後的,有三次握手的話,B返回的建立請求A就不會理睬了。

短連接與長連接?

上圖是一個短連接的過程演示,對於長連接,A與B完成一次讀寫之後,它們之間的連接並不會主動關閉,後續的讀寫操作會繼續使用這個連接。另外,由於長連接的實現比較困難,需要要求長連接在沒有數據通信時,定時發送數據包(心跳),以維持連接狀態,並且長連接對於伺服器的壓力也會很大,所以推送服務對於一般的開發者是非常難以實現的,這樣的話就出現了很多不同的大型廠商提供的消息推送服務。

進行TLS加密過程

  • Hello - 握手開始於客戶端發送Hello消息。包含服務端為了通過SSL連接到客戶端的所有信息,包括客戶端支持的各種密碼套件和最大SSL版本。伺服器也返回一個Hello消息,包含客戶端需要的類似信息,包括到底使用哪一個加密演算法和SSL版本。

  • 證書交換 - 現在連接建立起來了,伺服器必須證明他的身份。這個由SSL證書實現,像護照一樣。SSL證書包含各種數據,包含所有者名稱,相關屬性(功能變數名稱),證書上的公鑰,數字簽名和關於證書有效期的信息。客戶端檢查它是不是被CA驗證過的。註意伺服器被允許需求一個證書去證明客戶端的身份,但是這個只發生在敏感應用。

  • 密鑰交換 - 先使用RSA非對稱公鑰加密演算法(客戶端生成一個對稱密鑰,然後用SSL證書裡帶的伺服器公鑰將改對稱密鑰加密。隨後發送到服務端,服務端用伺服器私鑰解密,到此,握手階段完成。)或者DH交換演算法在客戶端與服務端雙方確定一將要使用的密鑰,這個密鑰是雙方都同意的一個簡單,對稱的密鑰,這個過程是基於非對稱加密方式和伺服器的公鑰/私鑰的。

  • 加密通信 - 在伺服器和客戶端加密實際信息是用到對稱加密演算法,用哪個演算法在Hello階段已經確定。對稱加密演算法用對於加密和解密都很簡單的密鑰,這個密鑰是基於第三步在客戶端與服務端已經商議好的。與需要公鑰/私鑰的非對稱加密演算法相反。

服務端的處理

靜態緩存、CDN

為了優化網站訪問速度並減少伺服器壓力,通常將html、js、css、文件這樣的靜態文件放在獨立的緩存伺服器或者部署在類似Amazon CloudFront的CDN雲服務上,然後根據緩存過期配置確定本次訪問是否會請求源伺服器來更新緩存。

負載均衡

負載均衡具體實現有多種,有直接基於硬體的F5,有操作系統傳輸層(TCP)上的 LVS,也有在應用層(HTTP)實現的反向代理(也叫七層代理),下麵簡單介紹一下最後者。

在請求發送到真正處理請求的伺服器之前,還需要將請求路由到適合的伺服器上,一個請求被負載均衡器拿到之後,需要做一些處理,比如壓縮請求(在nginx中gzip壓縮格式是預設配置在nginx.conf內的,所以預設開啟,如果不對數據量要求特別精細的話,預設配置完全可以滿足基本需求)、接收請求(接收完畢後才發給Server,提高Server處理效率),然後根據預定的路由演算法,將此次請求發送到某個後臺伺服器上。

其中需要提到的一點是反向代理,先回顧一下反向代理的原理:正向代理是將自己要訪問的資源告訴Proxy,讓Proxy幫你拿到數據返回給你,Proxy服務於Client,常用於FQ和跨許可權操作;反向代理也是將自己要訪問的資源告訴Proxy,讓Proxy幫你拿到數據返回給你,但是Proxy服務於Server,它會將請求接受完畢之後發送給某一合適的Server,這個時候Client是不知道是根據什麼規則並且也不知道最後是哪一個Server服務於它的,所以叫反向代理,常用於負載均衡、安全控制.

伺服器的處理

對於HTTPD(HTTP Daemon)在伺服器上部署,最常見的 HTTPD 有 Linux 上常用的 Apache 和 Nginx。對於Java平臺來說,Tomcat是Spring Boot也會預設選用的Servlet容器實現,Tomcat對於請求的處理如下:

  1. 請求到達Tomcat啟動時監聽的TCP埠。

  2. 解析請求中的各種信息之後創建一個Request對象並填充那些有可能被所引用的Servlet使用的信息,如參數,頭部、cookies、查詢字元串等。

  3. 創建一個Response對象,所引用的Servlet使用它來給客戶端發送響應。

  4. 調用Servlet的service方法,並傳入Request和Response對象。這裡Servlet會從Request對象取值,給Response寫值。

  5. 根據我們自己寫的Servlet程式或者框架攜帶的Servlet類做進一步的處理(業務處理、請求的進一步處理)

  6. 最後根據Servlet返回的Response生成相應的HTTP響應報文。

瀏覽器的渲染

瀏覽器的功能是從伺服器上取回你想要的資源,然後展示在瀏覽器視窗當中。資源通常是 HTML 文件,也可能是 PDF,圖片,或者其他類型的內容。也可以顯示其他類型的插件(瀏覽器擴展)。例如顯示PDF使用PDF瀏覽器插件。資源的位置通過用戶提供的 URI(Uniform Resource Identifier) 來確定。

瀏覽器解釋和展示 HTML 文件的方法,在 HTML 和 CSS 的標準中有詳細介紹。這些標準由 Web 標準組織 W3C(World Wide Web Consortium) 維護。

下麵會以Chrome中使用的瀏覽器引擎Webkit為例,根據上圖來簡單介紹瀏覽器的渲染。具體解析、渲染會涉及到非常多的細節,請參考HTML5渲染規範和對應的頁面GPU渲染實現。

HTML解析

瀏覽器拿到具體的HTML文檔之後,需要調用瀏覽器中使用的瀏覽器引擎中處理HTML的工具(HTML Parser)來將HTML文檔解析成為DOM樹,將以便外部介面(JS)調用。

  • 文檔內容解析:將一大串字元串解析為DOM之前需要從中分析出結構化的信息讓HTML解析器可以很方便地提取數據進行其他操作,所以對於文檔內容的解析是第一步。解析器有兩個處理過程——詞法分析(將字元串切分成符合特定語法規範的符號)與語法分析(根據符合語法規範的符號構建對應該文檔的語法樹)。

  • HTML解析:根據HTML語法,將HTML標記到語法樹上構建成DOM(Document Object Model)。

CSS解析

  • 根據CSS詞法和句法分析CSS文件和<style>標簽包含的內容以及style屬性的值

  • 每個CSS文件都被解析成一個樣式表對象(StyleSheet object),這個對象里包含了帶有選擇器的CSS規則,和對應CSS語法的對象

頁面渲染

解析完成後,瀏覽器引擎會通過DOM樹和CSS Rule樹來構造渲染樹。渲染樹的構建會產生Layout,Layout是定位坐標和大小,是否換行,各種position, overflow, z-index屬性的集合,也就是對各個元素進行位置計算、樣式計算之後的結果。

接下來,根據渲染樹對頁面進行渲染(可以理解為“畫”元素)。

當然,將這個渲染的過程完成並顯示到屏幕上會涉及到顯卡的繪製,顯存的修改,有興趣的讀者可以深入瞭解。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我們要做到不但會寫SQL,還要做到寫出性能優良的SQL語句。 1.使用表的別名(Alias): 當在SQL語句中連接多個表時, 請使用表的別名並把別名首碼於每個Column上。這樣一來,就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤。 2.表的索引: 索引是表的一個概念部分,用來提高 ...
  • 一、 軟體下載 Mysql是一個比較流行且很好用的一款資料庫軟體,如下記錄了我學習總結的mysql免安裝版的配置經驗,要安裝的朋友可以當做參考哦 mysql5.7 64位下載地址: https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19- ...
  • 1. 如何對評論進行分頁展示 一般情況下都是這樣寫 SELECT customer_id,title,content FROM product_comment WHERE audit_status = 1 AND product_id =199726 LIMIT 0,15;; 我們來看看它的執行計劃 ...
  • 一、代碼 說明:本文章須結合文章《block本質探尋一之記憶體結構》和《class和object_getClass方法區別》加以理解; //main.m //列印 分析:很顯然,只有c的值沒有改變,其它變數的值都改變了——為什麼,看下底層代碼實現; 二、main.cpp 分析: 1)C語言語法 <1> ...
  • public class GZIP { /** * 字元串的壓縮 * * @param str * 待壓縮的字元串 * @return 返回壓縮後的字元串 * @throws IOException */ public static String compress(String str)... ...
  • 一、代碼——命令行模式 //main.m block(20, 30); 分析:以下代碼的前提,因為我們知道block底層的構造就是上述結構體的構造,橋接的目的就是展示這樣的結構體內部是怎樣的; 二、調試 //lldb模式 1)第一個斷點 2)第二個斷點 3)轉入彙編 4)彙編界面 分析: 1)我們發 ...
  • 描述:剛開始遇到這個問題我一步一步去排除,最後發現在初始化地圖的時候,代碼混淆就有問題了, 問題描述:當跳顯示地圖的頁面APP閃退, 解決對比: 1:對於老版本百度sdk:代碼混淆時語句: -libraryjars libs/baidumapapi_v3_3_0.jar -libraryjars l ...
  • 本文內容搬運自公眾號 原文鏈接 本文主要內容:面向對象 預計閱讀時間:6分鐘 面向對象的方式 單例模式(字面量定義) var obj = {} 類的實例 var obj = new Object() 工廠創建 構造函數 扮演了三種角色,(普通函數、普通對象、類) 單例模式(字面量定義) var ob ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...