【面經(jīng)】字節(jié)跳動-后端開發(fā)-2019秋招

https://zhuanlan.zhihu.com/p/50186804

因?yàn)槊總€(gè)人的理解不太一樣,所以我在這里就不給出所謂的答案了,大家可以根據(jù)自己的理解加以描述,我只在一些地方做出一些提示。有的問題已經(jīng)忘了,大概也就這些了。


一面:

進(jìn)程和線程以及它們之間的區(qū)別(我通過對比多個(gè)面經(jīng),發(fā)現(xiàn)這道是必考題,劃重點(diǎn))

線程用于小任務(wù),而進(jìn)程用于更多的'重量級'的任務(wù)- 應(yīng)用基本執(zhí)行。 一個(gè)線程和進(jìn)程之間的另一個(gè)區(qū)別是,在同一進(jìn)程中的線程共享相同的地址空間,而不同的進(jìn)程沒有。 因此線程可以讀寫同樣的數(shù)據(jù)結(jié)構(gòu)和變量,便于線程之間的通信。?

定義方面:進(jìn)程是程序在某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動;線程是進(jìn)程中的一個(gè)執(zhí)行路徑。

進(jìn)程間的通信方式和對應(yīng)的同步方式,你用過嗎?具體怎么用?

進(jìn)程間的通信主要是指多個(gè)進(jìn)程間的數(shù)據(jù)交互。
同步主要指維護(hù)多個(gè)進(jìn)程或者線程之間數(shù)據(jù)的準(zhǔn)確性和一致性。

進(jìn)程通信方式:管道(Pipe)、信號(signal)、信號量(semophere)、消息隊(duì)列(message queue)、共享內(nèi)存(shared memory)、套接字(socket)。

同步方式:將線程串行化(wait notify方法來睡眠和喚醒線程)、互斥鎖(加鎖 mutex)、管程、臨界區(qū)、信號量

TCP和UDP的區(qū)別

TCP的優(yōu)點(diǎn): 可靠,穩(wěn)定。TCP的可靠體現(xiàn)在TCP在傳遞數(shù)據(jù)之前,會有三次握手來建立連接,而且在數(shù)據(jù)傳遞時(shí),有確認(rèn)、窗口、重傳、擁塞控制機(jī)制,在數(shù)據(jù)傳完后,還會斷開連接用來節(jié)約系統(tǒng)資源。TCP的邏輯通信信道是全雙工的可靠信道。?
TCP的缺點(diǎn): 慢,效率低,占用系統(tǒng)資源高,易被攻擊 TCP在傳遞數(shù)據(jù)之前,要先建連接,這會消耗時(shí)間,而且在數(shù)據(jù)傳遞時(shí),確認(rèn)機(jī)制、重傳機(jī)制、擁塞控制機(jī)制等都會消耗大量的時(shí)間,而且要在每臺設(shè)備上維護(hù)所有的傳輸連接,事實(shí)上,每個(gè)連接都會占用系統(tǒng)的CPU、內(nèi)存等硬件資源。 而且,因?yàn)門CP有確認(rèn)機(jī)制、三次握手機(jī)制,這些也導(dǎo)致TCP容易被人利用,實(shí)現(xiàn)DOS、DDOS、CC等攻擊。

UDP的優(yōu)點(diǎn): 快,比TCP稍安全 UDP沒有TCP的握手、確認(rèn)、窗口、重傳、擁塞控制等機(jī)制,UDP是一個(gè)無狀態(tài)的傳輸協(xié)議,所以它在傳遞數(shù)據(jù)時(shí)非???。沒有TCP的這些機(jī)制,UDP較TCP被攻擊者利用的漏洞就要少一些。但UDP也是無法避免攻擊的,比如:UDP Flood攻擊……
UDP的缺點(diǎn): 不可靠,不穩(wěn)定。因?yàn)閁DP沒有TCP那些可靠的機(jī)制,在數(shù)據(jù)傳遞時(shí),如果網(wǎng)絡(luò)質(zhì)量不好,就會很容易丟包。
面向數(shù)據(jù)報(bào):不能夠靈活的控制讀寫數(shù)據(jù)的次數(shù)和數(shù)量,應(yīng)用層交給UDP多長的報(bào)文, UDP原樣發(fā)送, 既不會拆分, 也不會合并。但是不會存在粘包的問題。

三次握手、四次揮手,為什么?

三次握手:為了保證接收方和發(fā)送方的接收能力和發(fā)送能力都正常。
四次揮手:為了釋放全雙工的信道。所以是單獨(dú)釋放和確認(rèn)的。

這是因?yàn)榉?wù)端在LISTEN狀態(tài)下,收到建立連接請求的SYN報(bào)文后,把ACK和SYN放在一個(gè)報(bào)文里發(fā)送給客戶端。而關(guān)閉連接時(shí),當(dāng)收到對方的FIN報(bào)文時(shí),僅僅表示對方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù),己方是否現(xiàn)在關(guān)閉發(fā)送數(shù)據(jù)通道,需要上層應(yīng)用來決定,因此,己方ACK和FIN一般都會分開發(fā)送。

TCP如何保證傳輸?shù)目煽啃裕?/h4>

TCP通過序列號、確認(rèn)應(yīng)答、超時(shí)重傳、擁塞控制來保證傳輸?shù)目煽啃?/p>

確認(rèn)應(yīng)答機(jī)制&序列號
TCP將每個(gè)字節(jié)的數(shù)據(jù)都進(jìn)行了編號,即為序列號。
每一個(gè)ACK都帶有對應(yīng)的確認(rèn)序列號,意思是告訴發(fā)送者,我已經(jīng)收到了哪些數(shù)據(jù);;下一次你從哪里開始發(fā)。

超時(shí)重傳&序列號
主機(jī)A發(fā)送數(shù)據(jù)給B之后, 可能因?yàn)榫W(wǎng)絡(luò)擁堵等原因, 數(shù)據(jù)無法到達(dá)主機(jī)B; 如果主機(jī)A在一個(gè)特定時(shí)間間隔內(nèi)沒有收到B發(fā)來的確認(rèn)應(yīng)答, 就會進(jìn)行重發(fā);主機(jī)A未收到B發(fā)來的確認(rèn)應(yīng)答,也可能是因?yàn)锳CK丟失了,因此主機(jī)B會收到很多重復(fù)數(shù)據(jù),這時(shí)候利用序列號可以使得主機(jī)B來實(shí)現(xiàn)數(shù)據(jù)報(bào)文的去重。

擁塞控制
每次發(fā)送數(shù)據(jù)包的時(shí)候, 將擁塞窗口和接收端主機(jī)反饋的窗口大小做比較, 取較小的值作為實(shí)際發(fā)送的窗口。
擁塞控制, 歸根結(jié)底是TCP協(xié)議想盡可能快的把數(shù)據(jù)傳輸給對方, 但是又要避免給網(wǎng)絡(luò)造成太大壓力的折中方案。

TCP如何提高傳輸效率:

TCP通過滑動窗口、流量控制、延遲應(yīng)答、捎帶應(yīng)答來提升傳輸?shù)男?/p>

滑動窗口機(jī)制
1. 窗口大小指的是無需等待確認(rèn)應(yīng)答而可以繼續(xù)發(fā)送數(shù)據(jù)的最大值.
2. 發(fā)送窗口內(nèi)字段的時(shí)候, 不需要等待任何ACK, 直接發(fā)送;
3. 收到第一個(gè)ACK后, 滑動窗口向后移動, 繼續(xù)發(fā)送下一個(gè)窗口字段的數(shù)據(jù); 依次類推;
4. 操作系統(tǒng)內(nèi)核為了維護(hù)這個(gè)滑動窗口, 需要開辟發(fā)送緩沖區(qū)來記錄當(dāng)前還有哪些數(shù)據(jù)沒有應(yīng)答; 只有確認(rèn)應(yīng)答過的數(shù)據(jù), 才能從緩沖區(qū)刪掉;
5. 窗口越大, 則網(wǎng)絡(luò)的吞吐率就越高

流量控制
接收端處理數(shù)據(jù)的速度是有限的. 如果發(fā)送端發(fā)的太快, 導(dǎo)致接收端的緩沖區(qū)被打滿, 這個(gè)時(shí)候如果發(fā)送端繼續(xù)發(fā)送, 就會造成丟包, 繼而引起丟包重傳等等一系列連鎖反應(yīng)。
1.接收端將自己可以接收的緩沖區(qū)大小放入TCP首部中的 "窗口大小" 字段, 通過ACK端通知發(fā)送端;
2.窗口大小字段越大, 說明網(wǎng)絡(luò)的吞吐量越?高;
3.接收端一旦發(fā)現(xiàn)自己的緩沖區(qū)快滿了, 就會將窗口大小設(shè)置成一個(gè)更小的值通知給發(fā)送端;
4.發(fā)送端接受到這個(gè)窗口之后, 就會減慢自己的發(fā)送速度;
5.如果接收端緩沖區(qū)滿了, 就會將窗口置為0; 這時(shí)發(fā)送?方不再發(fā)送數(shù)據(jù), 但是需要定期發(fā)送一個(gè)窗口

延遲應(yīng)答
如果接收數(shù)據(jù)的主機(jī)立刻返回ACK應(yīng)答, 這時(shí)候返回的窗口可能比較小.
窗口越大, 網(wǎng)絡(luò)吞吐量就越大, 傳輸效率就越高. 我們的目標(biāo)是在保證網(wǎng)絡(luò)不擁塞的情況下盡量提高傳輸效率;

捎帶應(yīng)答
在延遲應(yīng)答的基礎(chǔ)上, 我們發(fā)現(xiàn), 很多情況下, 客戶端服務(wù)器在應(yīng)用層也是 “一發(fā)一收” 的.
那么客戶端在發(fā)送數(shù)據(jù)的同時(shí),攜帶對方消息的報(bào)文序列號,來順帶通知對方,自己所接收到的報(bào)文情況

TCP的擁塞控制,具體過程是怎么樣的?UDP有擁塞控制嗎?如何解決?

TCP擁塞控制主要有四種方法,滑動窗口機(jī)制、慢啟動機(jī)制、擁塞避免機(jī)制、快速重傳與恢復(fù)。

滑動窗口機(jī)制
在發(fā)送數(shù)據(jù)的時(shí)候,將發(fā)送窗口內(nèi)的數(shù)據(jù)全部發(fā)送,才會停下來等待ACK,如果接收到對方的ACK信息,則滑動窗口前移。

慢啟動機(jī)制
在剛開始發(fā)送數(shù)據(jù)的時(shí)候,發(fā)送窗口取一個(gè)較小的值,來防止網(wǎng)絡(luò)擁塞,同時(shí)探測對方的接收能力。如果收到了對方的ACK回應(yīng),則按照對方要求的窗口大小來調(diào)整發(fā)送窗口,否則進(jìn)行窗口的擴(kuò)大。窗口大小一開始是1,之后進(jìn)行指數(shù)級別擴(kuò)大,其中ssthresh為估算的一個(gè)發(fā)送窗口閾值,當(dāng)窗口大小超過這個(gè)閾值,則之后的窗口每次擴(kuò)大1,不再是指數(shù)級別的擴(kuò)大。

還有一個(gè)概念是 AIMD(加法增大乘法減?。簾o論在慢啟動階段還是在擁塞控制階段,只要網(wǎng)絡(luò)出現(xiàn)超時(shí),就是將發(fā)送端的擁塞窗口(cwnd)置為1,ssthresh置為cwnd的一半,然后開始執(zhí)行慢啟動算法;當(dāng)網(wǎng)絡(luò)頻發(fā)出現(xiàn)超時(shí)情況時(shí),ssthresh就下降的很快,為了減少注入到網(wǎng)絡(luò)當(dāng)中的分組數(shù),而加法增大是執(zhí)行擁塞避免算法后,使擁塞窗口緩慢的增大,以防止網(wǎng)絡(luò)過早出現(xiàn)擁塞。

快速重傳
快重傳算法要求首先接收方收到一個(gè)失序的報(bào)文段后立刻發(fā)出重復(fù)確認(rèn),而不要等待自己發(fā)送數(shù)據(jù)時(shí)才進(jìn)行捎帶確認(rèn)。當(dāng)發(fā)送方收到ACK之后,進(jìn)行相應(yīng)的報(bào)文重傳。

快速恢復(fù)
當(dāng)發(fā)送方連續(xù)收到三個(gè)重復(fù)確認(rèn)時(shí)(代表丟了三個(gè)包),執(zhí)行“乘法減小”算法,慢啟動門限減半,從而預(yù)防網(wǎng)絡(luò)發(fā)生阻塞。由于發(fā)送方現(xiàn)在認(rèn)為網(wǎng)絡(luò)很可能沒有發(fā)生阻塞(因?yàn)闆]有超時(shí)),因此現(xiàn)在不執(zhí)行慢啟動算法,而是把擁塞窗口(cwnd)值設(shè)置為慢啟動門限減半后的值,然后開始執(zhí)行擁塞避免算法,擁塞窗口cwnd值線性增大

TCP和UDP是傳輸層協(xié)議(物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會話層、表示層、應(yīng)用層)

UDP沒有擁塞解決措施,當(dāng)網(wǎng)絡(luò)擁塞時(shí),直接丟掉UDP的包。解決方式:在傳輸層之上,利用UDP并改造:如RUDP(傳輸層)、RTP(應(yīng)用層和傳輸層之間)、UDT(應(yīng)用層)等


算法題:

一個(gè)鏈表,假設(shè)第一個(gè)節(jié)點(diǎn)我們定為下標(biāo)為1,第二個(gè)為2,那么下標(biāo)為奇數(shù)的結(jié)點(diǎn)是升序排序,偶數(shù)的結(jié)點(diǎn)是降序排序,如何讓整個(gè)鏈表有序?(分離鏈表,合并兩個(gè)有序鏈表)

先把兩個(gè)鏈表按照奇偶性分成兩個(gè)鏈表(偶數(shù)構(gòu)造成雙向鏈表);然后一個(gè)鏈表從頭部開始,另一個(gè)鏈表從尾部開始,插入第一個(gè)鏈表即可。

假設(shè)我們有一個(gè)隊(duì)列,可能存放幾千萬上億的數(shù)據(jù),我們應(yīng)該如何設(shè)計(jì)這個(gè)隊(duì)列?寫出來看看?(提問:這個(gè)隊(duì)列是只需要在頭尾添加和刪除嗎?雙向隊(duì)列?答:是的)

創(chuàng)建一個(gè)class,利用雙向鏈表構(gòu)造這個(gè)雙向隊(duì)列,實(shí)現(xiàn) getHead() getTail() addToHead() addToTail() popHead() popTail()

一個(gè)二維矩陣,從左到右是升序,從上到下是降序,找一個(gè)數(shù)是否存在于矩陣中(類似于二叉查找樹)

假設(shè)二維矩陣 g,查找的數(shù)為 t
先往右找(二分查找),找到 g[0][i]=a > t > g[0][i+1]=b,(所有行的 i+1, ... 的列的元素肯定全部小于 t,可以忽略),然后從 i 往下找(二分查找),找到 g[j][i] = c > t > g[j+1][i] = d,(說明 0~j 行的 0~i 列均大于 t,可以忽略),然后繼續(xù)往左找,再往下找,左下不斷交替,最終即可判斷是否存在 t


二面:

前面面試官已經(jīng)問了你三道算法了,那我就隨便問一道吧:翻轉(zhuǎn)鏈表(面試官:能不能用c寫)....(然后讓我一邊寫一邊跟他講redis)

翻轉(zhuǎn)鏈表:三個(gè)指針解決。p c n 分別記錄 前一個(gè)節(jié)點(diǎn),當(dāng)前節(jié)點(diǎn),后一個(gè)節(jié)點(diǎn)
初始化:前一個(gè)節(jié)點(diǎn) p = NULL,當(dāng)前節(jié)點(diǎn) c = head,后一個(gè)節(jié)點(diǎn) n = head.next;
運(yùn)行:c.next = p; p = n.next ; n.next = c; c = p ; p = n; n = c.next; 注意判斷是不是null
結(jié)束:while(n != null)

redis:

你知道redis有哪幾種數(shù)據(jù)類型嗎?你比較熟悉哪幾種?為什么?

redis有五種數(shù)據(jù)類型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

String(字符串)
string 是 redis 最基本的類型,你可以理解成與 Memcached 一模一樣的類型,一個(gè) key 對應(yīng)一個(gè) value。
string 類型是二進(jìn)制安全的。意思是 redis 的 string 可以包含任何數(shù)據(jù)。比如jpg圖片或者序列化的對象。
string 類型是 Redis 最基本的數(shù)據(jù)類型,string 類型的值最大能存儲 512MB。
常用命令:set、get、decr、incr、mget等。
注意:一個(gè)鍵最大能存儲512MB。

Hash(哈希)
Redis hash 是一個(gè)鍵值(key→value)對集合;是一個(gè) string 類型的 field 和 value 的映射表,hash 特別適合用于存儲對象。
每個(gè) hash 可以存儲 2^32 -1 鍵值對(40多億)。
常用命令:hget、hset、hgetall等。
應(yīng)用場景:存儲一些結(jié)構(gòu)化的數(shù)據(jù),比如用戶的昵稱、年齡、性別、積分等,存儲一個(gè)用戶信息對象數(shù)據(jù)。

List(列表)
Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個(gè)元素到列表的頭部(左邊)或者尾部(右邊)。
list類型經(jīng)常會被用于消息隊(duì)列的服務(wù),以完成多程序之間的消息交換。
常用命令:lpush、rpush、lpop、rpop、lrange等。
列表最多可存儲 2^32 - 1 元素 (4294967295, 每個(gè)列表可存儲40多億)。

Set(集合)
Redis的Set是string類型的無序集合。和列表一樣,在執(zhí)行插入和刪除和判斷是否存在某元素時(shí),效率是很高的。集合最大的優(yōu)勢在于可以進(jìn)行交集并集差集操作。Set可包含的最大元素?cái)?shù)量是4294967295。
集合是通過哈希表實(shí)現(xiàn)的,所以添加,刪除,查找的復(fù)雜度都是O(1)。
應(yīng)用場景:
1、利用交集求共同好友
2、利用唯一性,可以統(tǒng)計(jì)訪問網(wǎng)站的所有獨(dú)立IP。
3、好友推薦的時(shí)候根據(jù)tag求交集,大于某個(gè)threshold(臨界值的)就可以推薦。
常用命令:sadd、spop、smembers、sunion, srem, srange, sinter等。
集合中最大的成員數(shù)為 232 - 1(4294967295, 每個(gè)集合可存儲40多億個(gè)成員)。

zset(sorted set:有序集合)
Redis zset 和 set 一樣也是string類型元素的集合,且不允許重復(fù)的成員。
不同的是每個(gè)元素都會關(guān)聯(lián)一個(gè)double類型的分?jǐn)?shù)。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。
zset的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)。
sorted set是插入有序的,即自動排序。
常用命令:zadd、zrange、zrem、zcard等。
當(dāng)你需要一個(gè)有序的并且不重復(fù)的集合列表時(shí),那么可以選擇sorted set數(shù)據(jù)結(jié)構(gòu)。
應(yīng)用舉例:
(1)例如存儲全班同學(xué)的成績,其集合value可以是同學(xué)的學(xué)號,而score就可以是成績。
(2)排行榜應(yīng)用,根據(jù)得分列出topN的用戶等。

講講redis里面的哈希表吧

Redis對于hash沖突,采用的是鏈地址法(其他的解決沖突的方法是再哈希和開放地址(線性探測和二次探測))
Redis為了控制哈希表占用內(nèi)存的大小,采用雙哈希表結(jié)構(gòu),并逐步擴(kuò)大哈希表容量的策略。
Redis存儲一個(gè)對象時(shí),首先使用 zipmap又稱為small hash存儲。這樣會節(jié)省很多哈希自身所需要的元數(shù)據(jù)的存儲開銷。當(dāng)域字段field的數(shù)量超過限制范圍,或者字段值value的長度大小超過系統(tǒng)限定的字節(jié)數(shù),此時(shí)Redis將該zipmap轉(zhuǎn)化為正常的hash進(jìn)行存儲。

參考?http://www.itdecent.cn/p/7f53f5e683cf?源碼分析:

結(jié)構(gòu)

hash表的結(jié)構(gòu)定義如上。整個(gè)dict包含兩個(gè)hash table,每個(gè)table初始化為4的大小,dictEntry 則是真正存放數(shù)據(jù)的結(jié)構(gòu)。對于鍵值沖突的地方,采用鏈地址法

但是在 dict 擴(kuò)容縮容時(shí),需要分配新的 hashtable,然后進(jìn)行漸進(jìn)式搬遷,這時(shí)候兩個(gè) hashtable 存儲的分別是舊的 hashtable 和新的 hashtable。待搬遷結(jié)束后,舊的 hashtable 被刪除,新的 hashtable 取而代之。

rehash

擴(kuò)容:當(dāng) hash 表中元素的個(gè)數(shù)(即第一個(gè)hash表的used)等于第一維數(shù)組的長度(即第一個(gè)hash表的size)時(shí),就會開始擴(kuò)容,擴(kuò)容的新數(shù)組是原數(shù)組大小的 2 倍。不過如果 Redis 正在做 bgsave,為了減少內(nèi)存頁的過多分離 (Copy On Write),Redis 盡量不去擴(kuò)容 (dict_can_resize 標(biāo)志是否能夠擴(kuò)容),但是如果 hash 表已經(jīng)非常滿了,元素的個(gè)數(shù)已經(jīng)達(dá)到了第一維數(shù)組長度的 5 倍 (dict_force_resize_ratio),說明 hash 表已經(jīng)過于擁擠了,這個(gè)時(shí)候就會強(qiáng)制擴(kuò)容。

縮容:當(dāng) hash 表因?yàn)樵氐闹饾u刪除變得越來越稀疏時(shí),,Redis 會對 hash 表進(jìn)行縮容來減少 hash 表的第一維數(shù)組空間占用。縮容的條件是元素個(gè)數(shù)低于數(shù)組長度的 10%。縮容不會考慮 Redis 是否正在做 bgsave。

收縮或者擴(kuò)展哈希表需要將ht[0]表中的所有鍵全部rehash到ht[1]中,但是rehash操作不是一次性、集中式完成的,而是分多次,漸進(jìn)式,斷續(xù)進(jìn)行的,這樣才不會對服務(wù)器性能造成影響

漸進(jìn)式rehash(incremental rehashing)

漸進(jìn)式rehash的關(guān)鍵:
1、字典結(jié)構(gòu)dict中的一個(gè)成員rehashidx,當(dāng)rehashidx為-1時(shí)表示不進(jìn)行rehash,當(dāng)rehashidx值為0時(shí),表示開始進(jìn)行rehash。
2、在rehash期間,每次對字典的添加(只加到 ht[1])、刪除(ht[0] ht[1] 全部查找并刪除)、查找(先查找 ht[0],如果未找到再查 ht[1])、或更新操作時(shí),都會判斷是否正在進(jìn)行rehash操作,如果是,則順帶進(jìn)行單步rehash(調(diào)用_dictRehashStep 函數(shù),該函數(shù)調(diào)用 dictRehash(d, 1)),并將rehashidx+1。新添加到字典的key-val一律會被保存到ht[1]里面,而ht[0]不再進(jìn)行任何添加操作,這一措施保證了ht[0]包含的key-val對數(shù)量只增不減,并隨著rehash操作的執(zhí)行而最終變成空表。
3、dictRehash(dict* d, int n) 函數(shù)每次 rehash 前進(jìn) n 步(順序訪問 n 個(gè) ht[0].table 的非空 dictEntry),如果 dictEntry 一直為空,則訪問到 n*10 個(gè)空 dictEntry 之后,本次 rehash 結(jié)束。
4、啟動 redis 會啟動一個(gè) cron 定時(shí)任務(wù)(定時(shí)任務(wù)默認(rèn)每秒執(zhí)行 server.h CONFIG_DEFAULT_HZ=10 次),每次定時(shí)任務(wù)運(yùn)行 1ms 的 rehash,調(diào)用 dictRehash(d, 100),執(zhí)行100步rehash。
4、當(dāng)rehash時(shí)進(jìn)行完成時(shí),將rehashidx置為-1,表示完成rehash。同時(shí) ht[0]=ht[1],ht[1]=Null,更換表指針。

一個(gè)URL從瀏覽器輸入到響應(yīng)頁面,整個(gè)過程是怎么樣的,能講得多詳細(xì)就講多詳細(xì)。

你說HTTP可以進(jìn)行多路復(fù)用,具體是怎么復(fù)用?如果服務(wù)器掛掉或者客戶端掛掉,會怎么樣?

http1.1 通過設(shè)定 Connection:keep-alive 字段來保持TCP的長連接,從而能夠在一次建立連接的情況下處理多個(gè)請求。
下一個(gè)請求需要在上一個(gè)請求的響應(yīng)之后發(fā)送,因此會存在隊(duì)頭阻塞。
HTTP1.1進(jìn)一步地支持在持久連接上使用管道化(pipelining)特性。管道化允許客戶端在已發(fā)送的請求收到服務(wù)端的響應(yīng)之前發(fā)送下一個(gè)請求,借此來減少等待時(shí)間提高吞吐率。但是需要響應(yīng)的順序是按照請求順序進(jìn)行,因此也會存在隊(duì)頭阻塞。

http2 開啟了完全的多路復(fù)用:一個(gè)連接被多個(gè)流復(fù)用。一個(gè)流表示一次請求-響應(yīng)過程。
這個(gè)過程有兩個(gè)概念:流和幀。幀代表著最小的數(shù)據(jù)單位,每個(gè)幀會標(biāo)識出該幀屬于哪個(gè)流,流也就是多個(gè)幀組成的數(shù)據(jù)流。
多路復(fù)用,就是在一個(gè) TCP 連接中可以存在多條流。換句話說,也就是可以發(fā)送多個(gè)請求,對端可以通過幀中的標(biāo)識知道屬于哪個(gè)請求。通過這個(gè)技術(shù),可以避免 HTTP 舊版本中的隊(duì)頭阻塞問題,極大的提高傳輸性能。

掛掉,則一段時(shí)間之后,保活時(shí)間到期,則關(guān)閉?;蛘逿CP等待時(shí)間結(jié)束,關(guān)閉TCP連接?;蛘卟捎脩?yīng)用層周期發(fā)送心跳包來檢測是否對方還在。

好處:
減少服務(wù)端連接壓力,減少占用內(nèi)存,提升連接吞吐量;
連接數(shù)的減少改善了網(wǎng)絡(luò)擁塞狀況,慢啟動時(shí)間減少,擁塞和丟包恢復(fù)速度更快;
避免連接頻繁創(chuàng)建和關(guān)閉(三次連接、四次揮手);

HTTP的各種頭你了解嗎?每種頭具體是什么作用?說一下

四種方法
GET:獲取信息
POST:傳輸實(shí)體
PUT:上傳文件
DELETE:刪除文件

頭部信息:
Host (主機(jī)和端口號)
Connection (鏈接類型)
Upgrade-Insecure-Requests (升級為 HTTPS 請求)
User-Agent (瀏覽器名稱)
Accept (傳輸文件類型)
Referer (頁面跳轉(zhuǎn)處)
Accept-Encoding(文件編解碼格式)
Cookie (Cookie)
x-requested-with :XMLHttpRequest (是 Ajax 異步請求)

你說arp會進(jìn)行廣播,會造成網(wǎng)絡(luò)風(fēng)暴,那應(yīng)該怎么解決?

arp發(fā)出去之后,交換機(jī)會查找自己的 mac 緩存表,如果存在,則直接返回,不存在則按照 IP 選擇端口進(jìn)行發(fā)送,如果不存在 IP 的端口,則廣播。之后每個(gè)路由器都有隔離廣播的作用,其也緩存了 IP 對應(yīng)的端口,并向?qū)?yīng)的端口進(jìn)行發(fā)送。

你知道CDN嗎?說一下

BIO NIO AIO說一下?epoll了解嗎?用過嗎?具體調(diào)用OS什么方法?webSocket呢?

java 相關(guān)

創(chuàng)建進(jìn)程調(diào)用的是OS哪些方法?具體說說

我們聊聊JAVA吧,你了解JVM嗎?給我講講

JVM具體會在什么時(shí)候進(jìn)行垃圾回收?JMM具體說說?

垃圾回收算法具體說說?各種垃圾回收器了解嗎?什么時(shí)候執(zhí)行STOP THE WORLD?


三面:

感覺應(yīng)該是總監(jiān),很高冷。

說說項(xiàng)目?(沒啥興趣)

我們聊聊JAVA吧,現(xiàn)在我要求設(shè)計(jì)一個(gè)容器,容器滿的時(shí)候生產(chǎn)者阻塞,容器空的時(shí)候消費(fèi)者阻塞(我跟他講了一下BlockingQueue和Condition,然后用Condition來寫)

二叉樹的最大路徑。

好吧,今天就到這里了(哈???)

三面面完一度覺得自己涼透了,過兩天收到offer call,然后就收到offer了。白菜價(jià),很高興了。

總的來說,個(gè)人感覺頭條面試算法題不難(應(yīng)該是給我放水了,謝謝面試官),不過絕對不能做不出來?;A(chǔ)一定要牢固,一些細(xì)節(jié)問題一定要搞清楚,一般還會問一些設(shè)計(jì)問題,這種問題就要靠靈機(jī)一動了(其實(shí)主要還是看對各種原理的理解,例如說那道隊(duì)列的問題)。噢,對了,還有一件事,一面是要求自己寫測試用例運(yùn)行的,所以coding一定要快準(zhǔn)狠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容