阿里面試:“說一下從 url 輸入到返回請(qǐng)求的過程”
閱讀本文大概需要 8.5 分鐘。
前言
問題: 從瀏覽器地址欄輸入url到請(qǐng)求返回發(fā)生了什么?
先說為什么url要解析(也就是編碼)
我回答大概內(nèi)容是:因?yàn)榫W(wǎng)絡(luò)標(biāo)準(zhǔn)規(guī)定了URL只能是字母和數(shù)字,還有一些其它特殊符號(hào)(-_.~ ! * ' ( ) ; : @ & = + $ , / ? # [ ],特殊符號(hào)是我下來查的資料,實(shí)在背不住這么多,比較常見的就是不包括百分號(hào)和雙引號(hào)),而且如果不轉(zhuǎn)義會(huì)出現(xiàn)歧義,比如 http:www.baidu.com?key=value,假如我的key本身就包括等于=符號(hào),比如ke=y=value,就會(huì)出現(xiàn)歧義,你不知道=到底是連接key和value的符號(hào),還是說本身key里面就有=。大佬接著毒打我說,那url編碼的規(guī)則是什么呢,我說utf-8 大佬接著窮追不舍,為啥是utf-8呢,所有瀏覽器都是這樣嗎?中文的話用gb2312編碼嗎,還有就是萬一瀏覽器不是你說的這樣統(tǒng)一用utf-8,你怎么保證都是utf-8的編碼? 我支支吾吾的說,我了解的大概是這樣,不太清楚, 應(yīng)該和html本身的編碼格式有關(guān),然后怎么保證utf-8的編碼,我覺得可以用encodeURIComponent 大佬說encodeURIComponent比encodeURI有什么區(qū)別? 區(qū)別就是encodeURIComponent編碼范圍更廣,適合給參數(shù)編碼,encodeURI適合給URL本身(locaion.origin)編碼,當(dāng)然項(xiàng)目里一般都是用qs庫去處理
然后說說dns解析流程,并且html如何做dns優(yōu)化
<meta http-equiv="x-dns-prefetch-control" content="on" />
<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
第一次握手:主機(jī)A發(fā)送位碼為SYN=1的TCP包給服務(wù)器,并且隨機(jī)產(chǎn)生一個(gè)作為確認(rèn)號(hào)(這是tcp包的一部分),主機(jī)B收到SYN碼后直到A要求建立連接; 第二次握手:主機(jī)B收到請(qǐng)求后,向A發(fā)送確認(rèn)號(hào)(主機(jī)A的seq+1),syn=1,seq = 隨機(jī)數(shù) 的TCP包; 主機(jī)A收到后檢查確認(rèn)號(hào)是否正確,即第一次A發(fā)送的確認(rèn)號(hào)是否+1了,以及位碼ack是否為1,若正確,主機(jī)A會(huì)再發(fā)送確認(rèn)號(hào)(主機(jī)B的seq+1),ack=1,主機(jī)B收到后確認(rèn)seq值與ack=1則連接建立成功。
接著,大佬說出個(gè)加分題,我看你不是科班出身,能答多少是多少。問題是,從網(wǎng)卡把數(shù)據(jù)包傳輸出去到服務(wù)器發(fā)生了什么,提示我OSI參考模型
我說,先從局域網(wǎng)把數(shù)據(jù)發(fā)送到公司的交換機(jī)(如果交換機(jī)沒有緩存本地mac地址和IP地址的映射,此時(shí)會(huì)通過ARP協(xié)議來獲得),交換機(jī)的好處是可以隔離沖突域(因?yàn)橐蕴W(wǎng)用的是CSMA/CD協(xié)議,這個(gè)協(xié)議規(guī)定網(wǎng)線上同一時(shí)刻只能有一臺(tái)機(jī)器發(fā)送數(shù)據(jù)),這樣就可以不僅僅同一時(shí)刻只有一臺(tái)機(jī)器發(fā)送網(wǎng)絡(luò)包了 然后交換機(jī)再將數(shù)據(jù)發(fā)送到路由器,路由器相當(dāng)于公司網(wǎng)關(guān)(我們公司小),路由器具有轉(zhuǎn)發(fā)和分組數(shù)據(jù)包的功能(路由器通過選定的路由協(xié)議會(huì)構(gòu)造出路由表,同時(shí)不定期的跟相鄰路由器交換路由信息),然后這算是經(jīng)過了物理層,數(shù)據(jù)鏈路層(以太網(wǎng)),開始到網(wǎng)絡(luò)層進(jìn)行數(shù)據(jù)轉(zhuǎn)發(fā)了 然后路由器轉(zhuǎn)發(fā)IP數(shù)據(jù)報(bào),一般公司的IP地址都會(huì)經(jīng)過NAT轉(zhuǎn)換,讓內(nèi)網(wǎng)的ip也能夠訪問外網(wǎng),我們公司我注意了一下是192.168打頭的內(nèi)網(wǎng)ip地址。通過路由器的分組傳輸,所有數(shù)據(jù)到達(dá)服務(wù)器。 然后服務(wù)器的上層協(xié)議傳輸層協(xié)議開始發(fā)揮作用,根據(jù)tcp包里的端口號(hào),讓服務(wù)器特定的服務(wù)來處理到來的數(shù)據(jù)包,并且tcp是面向字節(jié)流的(tcp有四大特性,可靠傳輸、流量控制、擁塞控制、連接管理),所以我們node的request對(duì)象,它的監(jiān)聽事件data事件為什么要用字符串一起拼接起來呢(buffer),就是因?yàn)閠cp本身就是字節(jié)流,request對(duì)象使用的data(http層面)是tcp傳來的數(shù)據(jù)塊。 最后數(shù)據(jù)由傳輸層轉(zhuǎn)交給應(yīng)用層,也就是http服務(wù)(或者h(yuǎn)ttps),后端經(jīng)過一系列邏輯處理,返回給前端數(shù)據(jù)。
答完這里,我說大佬我只知道大概的流程,具體細(xì)節(jié)我不是很清楚,但自己后面會(huì)補(bǔ)上。。。
堅(jiān)決不給中國人發(fā)Offer的GitLab成立中國公司!立志3-5年上市,怕是聞到了韭菜香?瀏覽器首次加載資源成功時(shí),服務(wù)器返回200,此時(shí)瀏覽器不僅將資源下載下來,而且把response的header(里面的date屬性非常重要,用來計(jì)算第二次相同資源時(shí)當(dāng)前時(shí)間和date的時(shí)間差)一并緩存; 下一次加載資源時(shí),首先要經(jīng)過強(qiáng)緩存的處理,cache-control的優(yōu)先級(jí)最高,比如cache-control:no-cache,就直接進(jìn)入到協(xié)商緩存的步驟了,如果cache-control:max-age=xxx,就會(huì)先比較當(dāng)前時(shí)間和上一次返回200時(shí)的時(shí)間差,如果沒有超過max-age,命中強(qiáng)緩存,不發(fā)請(qǐng)求直接從本地緩存讀取該文件(這里需要注意,如果沒有cache-control,會(huì)取expires的值,來對(duì)比是否過期),過期的話會(huì)進(jìn)入下一個(gè)階段,協(xié)商緩存 協(xié)商緩存階段,則向服務(wù)器發(fā)送header帶有If-None-Match和If-Modified-Since的請(qǐng)求,服務(wù)器會(huì)比較Etag,如果相同,命中協(xié)商緩存,返回304;如果不一致則有改動(dòng),直接返回新的資源文件帶上新的Etag值并返回200; 協(xié)商緩存第二個(gè)重要的字段是,If-Modified-Since,如果客戶端發(fā)送的If-Modified-Since的值跟服務(wù)器端獲取的文件最近改動(dòng)的時(shí)間,一致則命中協(xié)商緩存,返回304;不一致則返回新的last-modified和文件并返回200;
我說強(qiáng)緩存會(huì)觸發(fā),這兩種,具體什么行為不知道,大概內(nèi)容如下:
1、先查找內(nèi)存,如果內(nèi)存中存在,從內(nèi)存中加載;
2、如果內(nèi)存中未查找到,選擇硬盤獲取,如果硬盤中有,從硬盤中加載;
3、如果硬盤中未查找到,那就進(jìn)行網(wǎng)絡(luò)請(qǐng)求;
4、加載到的資源緩存到硬盤和內(nèi)存;
// Date 減去 Last-Modified 值的 10% 作為緩存時(shí)間。
// Date:創(chuàng)建報(bào)文的日期時(shí)間, Last-Modified 服務(wù)器聲明文檔最后被修改時(shí)間
response_is_fresh = max(0,(Date - Last-Modified)) % 10
構(gòu)建DOM樹(DOM tree):從上到下解析HTML文檔生成DOM節(jié)點(diǎn)樹(DOM tree),也叫內(nèi)容樹(content tree); 構(gòu)建CSSOM(CSS Object Model)樹:加載解析樣式生成CSSOM樹; 執(zhí)行JavaScript:加載并執(zhí)行JavaScript代碼(包括內(nèi)聯(lián)代碼或外聯(lián)JavaScript文件); 構(gòu)建渲染樹(render tree):根據(jù)DOM樹和CSSOM樹,生成渲染樹(render tree); 渲染樹:按順序展示在屏幕上的一系列矩形,這些矩形帶有字體,顏色和尺寸等視覺屬性。 布局(layout):根據(jù)渲染樹將節(jié)點(diǎn)樹的每一個(gè)節(jié)點(diǎn)布局在屏幕上的正確位置; 繪制(painting):遍歷渲染樹繪制所有節(jié)點(diǎn),為每一個(gè)節(jié)點(diǎn)適用對(duì)應(yīng)的樣式,這一過程是通過UI后端模塊完成;
頁面渲染優(yōu)化
HTML文檔結(jié)構(gòu)層次盡量少,最好不深于六層; 腳本盡量后放,放在前即可; 少量首屏樣式內(nèi)聯(lián)放在標(biāo)簽內(nèi); 樣式結(jié)構(gòu)層次盡量簡單; 在腳本中盡量減少DOM操作,盡量緩存訪問DOM的樣式信息,避免過度觸發(fā)回流; 減少通過JavaScript代碼修改元素樣式,盡量使用修改class名方式操作樣式或動(dòng)畫; 動(dòng)畫盡量使用在絕對(duì)定位或固定定位的元素上; 隱藏在屏幕外,或在頁面滾動(dòng)時(shí),盡量停止動(dòng)畫; 盡量緩存DOM查找,查找器盡量簡潔; 涉及多域名的網(wǎng)站,可以開啟域名預(yù)解析
推薦閱讀:
七個(gè)開源的 SpringBoot 前后端分離項(xiàng)目,Star過千,快去收藏夾吃灰吧!
Optional 是個(gè)好東西,你真的會(huì)用么?
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
朕已閱 
評(píng)論
圖片
表情

