深入淺出經典面試題:從瀏覽器中輸入URL到頁面加載發生了什么 - Part 3


備注

因為文章太長,所以將它分為三部分,本文是第三部分。

第一部分深入淺出經典面試題:從瀏覽器中輸入URL到頁面加載發生了什么 - Part 1

第二部分深入淺出經典面試題:從瀏覽器中輸入URL到頁面加載發生了什么 - Part 2

第三部分深入淺出經典面試題:從瀏覽器中輸入URL到頁面加載發生了什么 - Part 3

HTTP/HTTPS請求和響應

前面TCP連接已經建立好了,意味着橋已經搭好了,下一步就該傳輸HTTP消息了。因為HTTP我們都很熟悉,很常見,也不是那么底層,理解起來輕松不少。
還是抓包來分析,不過這次不用Wireshark來抓,因為不太直觀,這次直接用Chrome自帶的Developer Tools。

HTTP 請求

下圖展示了HTTP請求Header
Request URL:就是請求的URL
Request Method: GET, POST, PUT,DELETE, OPTIONS, HEAD
接下來就是其他報文頭,常見的請求報頭有: Accept, Accept-Charset, Accept-Encoding, Accept-Language, Content-Type, Authorization, Cookie, User-Agent等。
 

HTTP 響應

下圖展示了HTTP響應Header

 

最常見的就是Status Code( 200, 302, 307, 404, 500),server等。

HTTP 10問

HTTP問題簡單,那就直接列舉幾個問題,有些問題我給出詳細答案。
1.  HTTP METHOD有哪幾種,分別是什么?
常見問題,不多解釋。
 
2. HTTP的PUT/DELETE/等使用時需要注意什么?
有一點需要特別注意,有的瀏覽器是不支持的,所以在使用和實現時需要仔細評估好自己客戶端的能力。
 
3. HTTP的OPTIONS用來做什么?
OPTIONS一般用來獲取目標資源的通信選項,例如確認允許的HTTP Method.下面的這個例子來在Mozilla官網 https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
 
請求
curl -X OPTIONS http://example.org -i
 
響應
HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Date: Thu, 13 Oct 2016 11:45:00 GMT
Expires: Thu, 20 Oct 2016 11:45:00 GMT
Server: EOS (lax004/2813)
x-ec-custom-error: 1
Content-Length: 0
 
看紅色的返回部分,意思是說該URL允許的HTTP Method 為OPTIONS、GET、HEAD以及POST。
 
那么OPTIONS一般用在哪里呢?是的,CORS。如果您開發過SPA,或者您的前端的邏輯和交互完全用JavaScript來實現的,肯定會碰到此問題。所謂JavaScript實現,目前比交流行的有VueJS,AngularJS,React等流行框架。如何解決這個問題?最常用的方法是是前端和后端在同一個域名下。如果不在同一個域名下,需要在后端實現支持CORS的功能,目前Spring/Spring Boot已經有類似功能支持CORS,實現起來蠻簡單的,具體可以參看 https://spring.io/blog/2015/06/08/cors-support-in-spring-framework,不在贅述。
 
關於CORS,最難的不是這里,在我遇到的Case里,比這個更復雜,如果前端是SPA,而且在某種情況下,訪問任何前端頁面都會進行跳轉,這是需求。但是因為是SPA的架構,會出現OPTIONS(這是瀏覽器關於CORS支持的流程),這會使整個HTTP 流程變得紊亂,也是一個很棘手的問題。
 
不管怎么說,CORS屬於安全性這一塊,后面在軟件安全(包括Web)方面專門寫吧。在過去幾年里,因為公司和客戶在產品安全和數據安全放在了一個很高的位置,而我又是去負責這一塊,所以自己在安全方面積累了大量的實戰經驗,非常寶貴。
 
4. 上述訪問qq的HTTP response里的server哪里不合適,需要注意什么?
server的值是squid/3.5.24,不合適之處在哪里?也許部分人是不清楚的。其實很簡單,不應該把squid的版本信息放在這里。為什么?
 
如果web server軟件是自己公司開發的,私有的,不開源的,這也罷了,沒人知道你的web server是怎么實現的,但這並不代表web  server沒有漏洞,不代表別人發現不了漏洞。
 
但如果用的是開源的,例如Apache HTTPd,Apache Tomcat,Ngnix等,就需要注意了,每個版本都有安全漏洞,而且這些安全漏洞都有專門的記錄,看看隔三差五報告的CVE,就知道漏洞多少了。所以,如果使用開源軟件,很容易將自己的web server處於一個具有潛在風險的位置,所以不要加上版本號。
 
騰訊作為全球頂級的大公司,這方面不注意,實在是有點說不過去。如果有騰訊的朋友看到這里,還是改過來吧。
 
和上面一樣,這也是屬於安全性問題,有時間我再寫吧。
 
5. Status Code 302與307的區別是什么?
都屬於跳轉,但是區別在哪里呢?
我們看看307在協議里是怎么定義的?參看rfc2616第10章節
10.3.8 307 Temporary Redirect
The requested resource resides temporarily under a different URI. Since the redirection MAY be altered on occasion, the client SHOULD continue to use the Request-URI for future requests. This response is only cacheable if indicated by a Cache-Control or Expires header field.
The temporary URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s) , since many pre-HTTP/1.1 user agents do not understand the 307 status. Therefore, the note SHOULD contain the information necessary for a user to repeat the original request on the new URI.
If the 307 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.
在 GET、HEAD 這些冪等的請求方式上,302、307 沒區別,但對於 POST 就不同了,大部分瀏覽器 都會 302 會將 POST 請求轉為 GET,而 307則不一樣,規范要求瀏覽器繼續向 Location 的地址 POST 內容。
舉個例子解釋一下,假設正在POST一個消息,里面的Body有1M內容,在307的情況下,這1M的內容會繼續發過去,但在302的情況下,則不會。
 
6. 在HTTP Response里Connection的用法需要注意什么?
不解釋過多,keep-alive,closed用法不一樣,根據實際情況而定,在優化網絡時經常用到。
需要注意的是,Connection在通信領域會一些場景下會造成一些麻煩,尤其是在監控某個HTTP Session的flow時。
 
7.  在HTTP Response里Strict-Transport-Security(HSTS)怎么用?
HSTS一般大公司都會用,在我實際的項目涉及到HTTPS,為了實現某個功能,HSTS成了一個跨不過去的坎,遇到過很大問題。大家自己多看看吧。
 
8. 可以抓HTTPS的包了解HTTP請求和響應嗎?有什么方法?
不多解釋,但提供2個軟件名字,Fiddler,HTTP Analyzer。
 
9. 為什么對性能要求高的場景下不使用HTTP作為協議?例如在商用里,RPC開源項目一般不使用HTTP作為傳輸協議?而在5G下使用HTTP協議呢?
有一點是需要注意的,HTTP的消息頭太多了,會造成消息體特別大,影響性能,而且有些場景下這些消息頭大部分都是無用的。
但是在5G里,為什么3GPP組織會采用HTTP協議作為各個reference point的interface的實現呢?大家體會一下。
 
10.  HTTP協議(包括HTTP/2.0)有了解嗎?
不多解釋,但是HTTP/2.0還是需要了解一下,優勢和缺點。
 

瀏覽器解析和渲染頁面

現在瀏覽器接收到了server的返回內容,接下來瀏覽器該把內容呈現給用戶了。
 
Server返回的內容有哪些呢?這里只以HTML頁面為例(API返回的JSON數據或XML數據不在討論范圍內)。
 
一個頁面一般包含HTML、CSS、 JS、 圖片等文件,那么瀏覽器收到這些文件后該如何渲染(render)他們呢?
 
以下部分很多參考下面2篇文章:
瀏覽器的組成
 
首先我們先了解一下瀏覽器的組件構成,以及每個組件的功能,下圖是瀏覽器包括的幾個部分:
  1. User Interface: UI組件包括地址欄,前進/后退按鈕,書簽菜單等。
  2. Browser Engine: 在UI組件和渲染引擎間采取一些action.
  3. Rendering engine : 負責顯示請求的內容。例如,如果是HTML頁面,它將解析HTML,CSS,並將解析的內容顯示在屏幕上。
不同的瀏覽器使用不同的渲染引擎:
  • IE使用Trident
  • Firefox使用Gecko
  • Safari使用WebKit
  • Chrome和Opera(版本15開始)使用Blink。它是基於Webkit開發的。
4.    Networking: 負責網絡調用,例如HTTP請求。在不同的平台有不同的實
5.    UI backend: 主要用來繪畫基本的UI元素,例如下拉框,Windows等。這個UI后台暴露一些通用的接口,並不依賴平台的。
6.    JavaScript interpreter. 用來解析和運行JavaScript code。
7.    Data storage. 數據持久化的那一層。瀏覽器可能需要存儲各種各樣的數據,例如Cookie。瀏覽器也得支持我們常用的LocalStorage, IndexedDB,WebSQL以及FileSystem。

 

渲染頁面的主要流程

 
下面是瀏覽器的渲染引擎的主要步驟。
 
渲染引擎解析HTML文檔,並將HTML包含的元素轉化為一個個DOM,並構建為一個 DOM樹。然后引擎開始解析來自CSS文件或直接嵌在HTML頁面的CSS樣式數據,這些樣式信息又會構建另外一個樹: 渲染樹
 
渲染樹包含了多個矩形,這些矩形包含了顏色,大小,位置等屬性,而且會按照對應的順序顯示在屏幕上。
 
當渲染樹構造完畢后,接下來進入布局的程序,在這個程序里,渲染引擎會給每個DOM元素安排精確的坐標,並根據坐標在屏幕上顯示。
 
接下來是遍歷渲染樹,UI Backend層會將一個個DOM元素繪畫在屏幕上繪畫出來。
 
需要注意的是,上面是一個漸進的過程,理解這一點非常重要。但是為了得到更好的用戶體驗,瀏覽器會邊解析邊渲染,它並不會等到所有HTML解析完了才開始構造和布局渲染樹。當部分內容正在解析渲染時,另外一部分正從網絡那邊下載下來呢。
 
下面2個圖是WebKit和Gecko的渲染引擎的流程,我們發現他們大致相同的。

 

下面是DOM樹,渲染樹的樹形結構。

 

渲染引擎是單線程工作的,除了網絡操作,其他所有的都是單線程的。在Firefox和Safari,它們自己就是主線程,而Chrome就是每個tab處理主線程。
 
網絡操作則由多個並列線程去執行,但數量也是受限的,一般在2-6個。
 
瀏覽器的主線程是一個無限的事件循環,而且一直保持進程alive,一直等着各種事件(例如繪畫事件,布局事件),並處理他們。
 
瀏覽器渲染10問
1.   瀏覽器的組成部分是什么?
2.  各個主流瀏覽器的渲染引起是什么?
3.  瀏覽器顯示頁面的主要流程是什么?
4.  您在做開發和測試時,有哪些瀏覽器(包括手機)存在兼容性問題較多?
       遇見最多的是Samsung手機和Huawei手機,有時一個兼容性需要花費大量時間去調研和修復,可能是Samsung和Huawei定制的太厲害了,不兼容一些特性吧。
5.  渲染引擎是單線程還是多線程?
6.  瀏覽器的網絡操作一般由幾個線程去執行?
7.  DOM樹,渲染樹是什么?
8.  為了獲得更好的用戶體驗,我們應該在頁面做些什么改進?
9.  瀏覽器是如何打開PDF,Word等文檔的?
10. 如果讓你開發一個瀏覽器,設計思路有哪些?

Web優化

我們知道,人的耐心是有限的,一個頁面如果超過8s,人基本上不會等了,這會對業務產生巨大影響。我們該如何去優化頁面呢?
 
思路很簡單,就是按照我們前面介紹的幾大步驟去優化。我們先回顧一下幾大步驟:
1.     DNS查詢
2.    TCP連接
3.    發送HTTP請求
4.    Server處理HTTP請求並返回HTTP報文
5.    瀏覽器解析並render頁面
6.    HTTP連接斷開
 
當我想總結一下的時候,雅虎在10多年就總結出來一些經驗,參看這里( https://developer.yahoo.com/performance/rules.html)。
這是10多年前的經驗,隨着科技的發展,一些新的經驗又出現了,可以容易想到的是:
1.  盡量將server離用戶近一些,例如人處在中國訪問Apple,應該是Apple中國站提供服務,GSLB很重要。
2. 不要把layout嵌入一層又一層,簡單說就是嵌套別太深,不然影響解析和渲染性能。
3. 有些數據可以在后台處理的,就不要在前端通過JavaScript處理了。
4. 如果請求過大,Load Balance這些手段還是要上的。
5. 保持HTTP連接,合理設置Connection。
6. 后台事件性能要高,能夠及時將結果返回給用戶。
當然涉及到高可用,高性能等那是另外一個話題。

總結

這道面試題非常經典,考察的知識非常豐富,跨度較大,如果沒有幾年的經驗,是很難完全掌握的,所以想答好其實不容易的。對這個問題,基本上可以根據我的經驗回答,也算是對這些年來在這方面的知識的一個總結。但同時,我也參考了一些資料,感謝他們。在參考的地方,我都把URL列出來了。
 
寫這篇文章耗費了大量時間,我覺得挺有意義,但是也不能保證里面的內容全都是正確或准確的,如果您有任何問題可以通過以下方式聯系我,以便我進一步改正並更新。
 
個人微信:terryisme                                    公眾號:terrymemo

                      

下載

寫到這里,三部分已經寫完,在這里放上全文的PDF文檔供大家參考,可能后面會更改,如果有新的文檔,我將保持更新。

下載 2018/12/04版本 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM