一個網頁開啟的全過程分析
1、概要
從使用者在瀏覽器輸入域名開始,到web頁面載入完畢,這是一個說複雜不復雜,說簡單不簡單的過程,下文暫且把這個過程稱作網頁載入過程。下面我將依靠自己的經驗,總結一下整個過程。如有錯漏,歡迎指正。
閱讀本文需要讀者已有一定的計算機知識,瞭解TCP、DNS等。
2、分析
眾所周知,開啟一個網頁的過程中,瀏覽器會因頁面上的css/js/image等靜態資源會多次發起連線請求,所以我們暫且把這個網頁載入過程分成兩部分:
- html(jsp/php/aspx) 頁面載入(假設存在簡單的Nginx負載均衡)
- css/js/image等 網頁靜態資源載入(假設使用CDN)
2.1 頁面載入
先上一張圖,直觀明瞭地讓大家瞭解下基本流程,然後我們再逐一分析。
2.1.1 DNS解析
什麼是DNS解析?當用戶輸入一個網址並按下回車鍵的時候,瀏覽器得到了一個域名。而在實際通訊過程中,我們需要的是一個IP地址。因此我們需要先把域名轉換成相應的IP地址,這個過程稱作DNS解析。
1) 瀏覽器首先搜尋瀏覽器自身快取的DNS記錄。
或許很多人不知道,瀏覽器自身也帶有一層DNS快取。Chrome 快取1000條DNS解析結果,快取時間大概在一分鐘左右。
(Chrome瀏覽器通過輸入:chrome://net-internals/#dns 開啟DNS快取頁面)
2) 如果瀏覽器快取中沒有找到需要的記錄或記錄已經過期,則搜尋hosts檔案和作業系統快取。
在Windows作業系統中,可以通過 ipconfig /displaydns 命令檢視本機當前的快取。
通過hosts檔案,你可以手動指定一個域名和其對應的IP解析結果,並且該結果一旦被使用,同樣會被快取到作業系統快取中。
Windows系統的hosts檔案在%systemroot%\system32\drivers\etc下,linux系統的hosts檔案在/etc/hosts下。
3) 如果在hosts檔案和作業系統快取中沒有找到需要的記錄或記錄已經過期,則向域名解析伺服器傳送解析請求。
其實第一臺被訪問的域名解析伺服器就是我們平時在設定中填寫的DNS伺服器一項,當作業系統快取中也沒有命中的時候,系統會向DNS伺服器正式發出解析請求。這裡是真正意義上開始解析一個未知的域名。
一般一臺域名解析伺服器會被地理位置臨近的大量使用者使用(特別是ISP的DNS),一般常見的網站域名解析都能在這裡命中。
4) 如果域名解析伺服器也沒有該域名的記錄,則開始遞迴+迭代解析。
這裡我們舉個例子,如果我們要解析的是mail.google.com。
首先我們的域名解析伺服器會向根域伺服器(全球只有13臺)發出請求。顯然,僅憑13臺伺服器不可能把全球所有IP都記錄下來。所以根域伺服器記錄的是com域伺服器的IP、cn域伺服器的IP、org域伺服器的IP……。如果我們要查詢.com結尾的域名,那麼我們可以到com域伺服器去進一步解析。所以其實這部分的域名解析過程是一個樹形的搜尋過程。
根域伺服器告訴我們com域伺服器的IP。
接著我們的域名解析伺服器會向com域伺服器發出請求。根域伺服器並沒有mail.google.com的IP,但是卻有google.com域伺服器的IP。
接著我們的域名解析伺服器會向google.com域伺服器發出請求。...
如此重複,直到獲得mail.google.com的IP地址。
為什麼是遞迴:問題由一開始的本機要解析mail.google.com變成域名解析伺服器要解析mail.google.com,這是遞迴。
為什麼是迭代:問題由向根域伺服器發出請求變成向com域伺服器發出請求再變成向google.com域發出請求,這是迭代。
5) 獲取域名對應的IP後,一步步向上返回,直到返回給瀏覽器。
2.1.2 發起TCP請求
瀏覽器會選擇一個大於1024的本機埠向目標IP地址的80埠發起TCP連線請求。經過標準的TCP握手流程,建立TCP連線。
關於TCP協議的細節,這裡就不再闡述。這裡只是簡單地用一張圖說明一下TCP的握手過程。如果不瞭解TCP,可以選擇跳過此段,不影響本文其他部分的瀏覽。
2.1.3 發起HTTP請求
其本質是在建立起的TCP連線中,按照HTTP協議標準傳送一個索要網頁的請求。
2.1.4 負載均衡
什麼是負載均衡?當一臺伺服器無法支援大量的使用者訪問時,將使用者分攤到兩個或多個伺服器上的方法叫負載均衡。
什麼是Nginx?Nginx是一款面向效能設計的HTTP伺服器,相較於Apache、lighttpd具有佔有記憶體少,穩定性高等優勢。
負載均衡的方法很多,Nginx負載均衡、LVS-NAT、LVS-DR等。這裡,我們以簡單的Nginx負載均衡為例。關於負載均衡的多種方法詳情大家可以Google一下。
Nginx有4種類型的模組:core、handlers、filters、load-balancers。
我們這裡討論其中的2種,分別是負責負載均衡的模組load-balancers和負責執行一系列過濾操作的filters模組。
1) 一般,如果我們的平臺配備了負載均衡的話,前一步DNS解析獲得的IP地址應該是我們Nginx負載均衡伺服器的IP地址。所以,我們的瀏覽器將我們的網頁請求傳送到了Nginx負載均衡伺服器上。
2) Nginx根據我們設定的分配演算法和規則,選擇一臺後端的真實Web伺服器,與之建立TCP連線、並轉發我們瀏覽器發出去的網頁請求。
Nginx預設支援 RR輪轉法 和 ip_hash法 這2種分配演算法。
前者會從頭到尾一個個輪詢所有Web伺服器,而後者則對源IP使用hash函式確定應該轉發到哪個Web伺服器上,也能保證同一個IP的請求能傳送到同一個Web伺服器上實現會話粘連。
也有其他擴充套件分配演算法,如:
fair:這種演算法會選擇相應時間最短的Web伺服器
url_hash:這種演算法會使得相同的url傳送到同一個Web伺服器
3) Web伺服器收到請求,產生響應,並將網頁傳送給Nginx負載均衡伺服器。
4) Nginx負載均衡伺服器將網頁傳遞給filters鏈處理,之後發回給我們的瀏覽器。
而Filter的功能可以理解成先把前一步生成的結果處理一遍,再返回給瀏覽器。比如可以將前面沒有壓縮的網頁用gzip壓縮後再返回給瀏覽器。
2.1.5 瀏覽器渲染
1) 瀏覽器根據頁面內容,生成DOM Tree。根據CSS內容,生成CSS Rule Tree(規則樹)。呼叫JS執行引擎執行JS程式碼。
2) 根據DOM Tree和CSS Rule Tree生成Render Tree(呈現樹)
3) 根據Render Tree渲染網頁
但是在瀏覽器解析頁面內容的時候,會發現頁面引用了其他未載入的image、css檔案、js檔案等靜態內容,因此開始了第二部分。
2.2 網頁靜態資源載入
以阿里巴巴的淘寶網首頁的logo為例,其url地址為 img.alicdn.com/tps/i2/TB1bNE7LFXXXXaOXFXXwFSA1XXX-292-116.png_145x145.jpg
我們清楚地看到了url中有cdn字樣。
什麼是CDN?如果我在廣州訪問杭州的淘寶網,跨省的通訊必然造成延遲。如果淘寶網能在廣東建立一個伺服器,靜態資源我可以直接從就近的廣東伺服器獲取,必然能提高整個網站的開啟速度,這就是CDN。CDN叫內容分發網路,是依靠部署在各地的邊緣伺服器,使使用者就近獲取所需內容,降低網路擁塞,提高使用者訪問響應速度。
接下來的流程就是瀏覽器根據url載入該url下的圖片內容。本質上是瀏覽器重新開始第一部分的流程,所以這裡不再重複闡述。區別只是負責均衡伺服器後端的伺服器不再是應用伺服器,而是提供靜態資源的伺服器。