网络相关面试题(持续更新)
1.瀏覽器輸入www.baidu.com回車,會發(fā)生什么?
(dns過程+路由器和交換機+操作系統(tǒng)網(wǎng)絡協(xié)議棧處理+web服務業(yè)務邏輯處理)
1.域名解析成IP
每個主機在網(wǎng)絡中都是IP為標識的,IP才是主機在網(wǎng)絡中的位置,域名只是為了方便用戶記憶而已,這就要求瀏覽器能夠識別域名并且將其轉化為對應的IP地址
所以瀏覽器會有一個DNS緩存,其中記錄了一些域名與IP的對應關系,供瀏覽器快速查找需要的IP。但是這個DNS緩存不可能存下所有的域名-IP地址,何況IP地址有時候還會變化,因此當在瀏覽器DNS緩存中沒有找到的時候,就要先向DNS服務器請求域名解析,DNS域名解析時用的是UDP協(xié)議。
①客戶端從瀏覽器中輸入www.baidu.com網(wǎng)站網(wǎng)址后回車,首先瀏覽器會查詢?yōu)g覽器本身的DNS緩存,一般只有幾分鐘的緩存,找到了就返回域名對應的IP;如果找不到,系統(tǒng)就會查詢本地hosts文件和本地DNS緩存信息,如果找到了,就返回域名對應IP;
②如果沒有找到對應的域名解析記錄,那么那么系統(tǒng)會把瀏覽器的解析請求,交給客戶端本地設置的DNS服務器地址解析(稱為Local DNS,LDNS),如果LDNS服務的本地緩存有對應的解析記錄,就會直接返回IP地址;
③如果沒有,LDNS會負責繼續(xù)請求其他DNS服務器;此時就是外網(wǎng)的DNS服務器了,先是根域名服務器,根據(jù)瀏覽器得到的域名,根域名服務器看到.com,會返回.com的頂級域名服務器的ip給LDNS;然后LDNS通過頂級域名服務器的ip,找到了頂級域名服務器,.com頂級域名服務器看到了是找baidu.com一級域名服務器,就將其服務器的ip返回給LDNS;然后一層一層往下找,直到找到了www.baidu.com的DNS記錄,并得到對應的IP地址,這時候LDNS會把找到的www.baidu.com的ip發(fā)送給客戶端瀏覽器,并記錄在緩存中,以便未來再次訪問。
④客戶端瀏覽器收到ip之后,就可以通過ip地址找到對應的web服務器了,即服務端主機;接下來就是三次握手建立連接了
2.與目的主機進行TCP連接(三次握手)
得到域名對應的ip地址后,也就表示可以將數(shù)據(jù)送達到目的主機了,即可以向服務器發(fā)送http請求了,但是http是應用層協(xié)議,tcp是傳輸層,所以發(fā)送http請求之前,開始我們常說的三次握手。Http請求是使用TCP進行傳輸?shù)?#xff0c;可以保證可靠傳輸,并且有序,需要建立連接,才能進行數(shù)據(jù)傳輸。
3.發(fā)送和接收數(shù)據(jù)
建立連接之后,就可以發(fā)送數(shù)據(jù)了,即發(fā)送http請求
以get方法為例:
①瀏覽器向服務器發(fā)送get方法報文
②該get方法報文通過tcp-》ip-》mac-》網(wǎng)關-》目的主機
③目的主機收到數(shù)據(jù)幀,通過ip-tcp-http,http協(xié)議單元回應http協(xié)議格式封裝好的HTML形式數(shù)據(jù);
④該HTML數(shù)據(jù)通過tcp-》ip-》mac-》網(wǎng)關-》我的主機
⑤我的主機收到數(shù)據(jù)幀,通過ip-tcp-http-瀏覽器,以網(wǎng)頁形式顯式HTML
4.與目的主機斷開TCP連接(四次揮手)
數(shù)據(jù)傳輸結束之后需要斷開連接,與建立連接不同,斷開連接需要多一次手,四次揮手
2. tcp三次握手,四次揮手的過程?
三次握手
1.客戶端的協(xié)議棧向服務器端發(fā)送了 SYN 包,并告訴服務器端當前發(fā)送序列號 j,客戶端進入 SYNC_SENT 狀態(tài);
2.服務器端的協(xié)議棧收到這個包之后,和客戶端進行 ACK 應答,應答的值為 j+1,表示對 SYN 包 j 的確認,同時服務器也發(fā)送一個 SYN 包,告訴客戶端當前我的發(fā)送序列號為 k,服務器端進入 SYNC_RCVD 狀態(tài);
3.客戶端協(xié)議棧收到 ACK 之后,使得應用程序從 connect 調用返回,表示客戶端到服務器端的單向連接建立成功,客戶端的狀態(tài)為 ESTABLISHED,同時客戶端協(xié)議棧也會對服務器端的 SYN 包進行應答,應答數(shù)據(jù)為 k+1;
4.應答包到達服務器端后,服務器端協(xié)議棧使得 accept 阻塞調用返回,這個時候服務器端到客戶端的單向連接也建立成功,服務器端也進入 ESTABLISHED 狀態(tài)。
四次揮手的過程:
1.首先,一方應用程序調用 close,我們稱該方為主動關閉方,該端的 TCP 發(fā)送一個 FIN 包,表示需要關閉連接。之后主動關閉方進入 FIN_WAIT_1 狀態(tài)
2.接著,接收到這個 FIN 包的對端執(zhí)行被動關閉。這個 FIN 由 TCP 協(xié)議棧處理,我們知道,TCP 協(xié)議棧為 FIN 包插入一個文件結束符 EOF 到接收緩沖區(qū)中,應用程序可以通過 read 調用來感知這個 FIN 包。一定要注意,這個 EOF 會被放在已排隊等候的其他已接收的數(shù)據(jù)之后,這就意味著接收端應用程序需要處理這種異常情況,因為 EOF 表示在該連接上再無額外數(shù)據(jù)到達。此時,被動關閉方進入 CLOSE_WAIT 狀態(tài)。
3.接下來,被動關閉方將讀到這個 EOF,于是,應用程序也調用 close 關閉它的套接字,這導致它的 TCP 也發(fā)送一個 FIN 包。這樣,被動關閉方將進入 LAST_ACK 狀態(tài)。
4.最終,主動關閉方接收到對方的 FIN 包,并確認這個 FIN 包。主動關閉方進入 TIME_WAIT 狀態(tài),而接收到 ACK 的被動關閉方則進入 CLOSED 狀態(tài)。進過 2MSL 時間之后,主動關閉方也進入 CLOSED 狀態(tài)。
"每個方向都需要一個 FIN 和一個 ACK,因此通常被稱為四次揮手"3.為什么連接的時候是三次握手,關閉的時候卻是四次握手?為什么不能用兩次握手進行連接?
為了實現(xiàn)可靠數(shù)據(jù)傳輸,TCP 協(xié)議的通信雙?,都必須維護?個序列號. 以標識發(fā)送出去的數(shù)據(jù)包中,哪些是已經(jīng)被對?收到的。 三次握?的過程即是通信雙?相互告知序列號起始值,并確認對?已經(jīng)收到了序列號起始值的必經(jīng)步驟。 "如果只是兩次握?, ?多只有連接發(fā)起?的起始序列號能被確認, 另??選擇的序列號則得不到確 認。"4.為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL(最大報文段生存時間)才能返回到CLOSE狀態(tài)?
"只有發(fā)起連接終止的一方會進入 TIME_WAIT 狀態(tài)。"1.TIME_WAIT 的作用
1.首先,這樣做是為了確保最后的 ACK 能讓被動關閉方接收,從而幫助其正常關閉。 TCP 在設計的時候,做了充分的容錯性設計,比如,TCP 假設報文會出錯,需要重傳. 在這里,如果圖中主機 1 的 ACK 報文沒有傳輸成功,那么主機 2 就會重新發(fā)送 FIN 報文。如果主機 1 沒有維護 TIME_WAIT 狀態(tài),而直接進入 CLOSED 狀態(tài)。 它就失去了當前狀態(tài)的上下文,只能回復一個 RST 操作,從而導致被動關閉方出現(xiàn)錯誤現(xiàn)在主機 1 知道自己處于 TIME_WAIT 的狀態(tài),就可以在接收到 FIN 報文之后,重新發(fā)出一個 ACK 報文, 使得主機 2 可以進入正常的 CLOSED 狀態(tài)。 2.第二個理由和連接“化身”和報文迷走有關系,為了讓舊連接的重復分節(jié)在網(wǎng)絡中自然消失。 在網(wǎng)絡中,經(jīng)常會發(fā)生報文經(jīng)過一段時間才能到達目的地的情況. 產生的原因是多種多樣的;"如路由器重啟,鏈路突然出現(xiàn)故障等。" 如果迷走報文到達時,發(fā)現(xiàn) TCP 連接四元組(源 IP,源端口,目的 IP,目的端口)所代表的連接不復存在,那么很簡單,這個報文自然丟棄。"考慮這樣一個場景": 在原連接中斷后,又重新創(chuàng)建了一個原連接的“**化身**”,說是化身其實是因為這個連接和原先的連接四元組完全相同,如果迷失報文經(jīng)過一段時間也到達,那么這個報文會被誤認為是連接“化身”的一個 TCP 分節(jié),這樣就會對 TCP 通信產生影響。 所以,TCP 就設計出了這么一個機制,經(jīng)過 2MSL 這個時間,足以讓兩個方向上的分組都被丟棄, 使得原來連接的分組在網(wǎng)絡中都自然消失,再出現(xiàn)的分組一定都是新化身所產生的。劃重點,"2MSL 的時間是從主機 1 接收到 FIN 后發(fā)送 ACK 開始計時的" 如果在 TIME_WAIT 時間內,因為主機1的 ACK 沒有傳輸?shù)街鳈C 2, 主機 1 又接收到了主機 2 重發(fā)的 FIN 報文,那么 2MSL 時間將重新計時.因為2MSL 的時間,目的是為了讓舊連接的所有報文都能自然消亡, 現(xiàn)在主機1重新發(fā)送了 ACK 報文,自然需要重新計時,以便防止這個ACK 報文對新可能的連接化身造成干擾。5.如果已經(jīng)建立了tcp連接,但是客戶端突然出現(xiàn)故障了怎么辦?
TCP 協(xié)議有一個保活機制。 這個機制的原理是這樣的:
定義?個時間段,在這個時間段內,如果沒有任何連接相關的活動,TCP 保活機制會開始作?,每隔?個時間間隔,發(fā)送?個探測報?,該探測報?包含的數(shù)據(jù)?常少,如果連續(xù)?個探測報?都沒有得到響應,則認為當前的TCP 連接已經(jīng)死亡,系統(tǒng)內核將錯誤信息通知給上層應?程序。
在 Linux 內核可以有對應的參數(shù)可以設置保活時間、保活探測的次數(shù)、保活探測的時間間隔,以下都為默認值:
net.ipv4.tcp_keepalive_time=7200 net.ipv4.tcp_keepalive_intvl=75 net.ipv4.tcp_keepalive_probes=9tcp_keepalive_time=7200:表示保活時間是 7200 秒(2?時),也就 2 ?時內如果沒有任何連接相關的活動,則會啟動保活機制
tcp_keepalive_intvl=75:表示每次檢測間隔 75 秒;
tcp_keepalive_probes=9:表示檢測 9 次?響應,認為對?是不可達的,從?中斷本次的連接
也就是說在 Linux 系統(tǒng)中,最少需要經(jīng)過 2 ?時 11 分 15 秒才可以發(fā)現(xiàn)?個「死亡」連接。
這個時間是有點?的,我們也可以根據(jù)實際的需求,對以上的保活相關的參數(shù)進?設置。
如果開啟了 TCP 保活,需要考慮以下幾種情況:
第?種,對端程序是正常?作的。 當 TCP 保活的探測報?發(fā)送給對端, 對端會正常響應,這樣 TCP 保活時間會被重置,等待下?個 TCP 保活時間的到來。
第?種,對端程序崩潰并重啟。 當 TCP 保活的探測報?發(fā)送給對端后,對端是可以響應的,但由于沒有該連接的有效信息,會產??個 RST 報?,這樣很快就會發(fā)現(xiàn) TCP 連接已經(jīng)被重置。
第三種,是對端程序崩潰,或對端由于其他原因導致報?不可達。 當 TCP 保活的探測報?發(fā)送給對端后,?沉?海,沒有響應,連續(xù)幾次,達到保活探測次數(shù)后,TCP 會報告該 TCP 連接已經(jīng)死亡。
6.如果服務器上存在大量 CLOSE_WAIT 情況,如何處理?
close_wait是被動關閉連接是形成的,根據(jù)TCP狀態(tài)機,服務器端收到客戶端發(fā)送的FIN,TCP協(xié)議棧會自動發(fā)送ACK,鏈接進入close_wait狀態(tài)。
但如果服務器端不執(zhí)行socket的close()操作,狀態(tài)就不能由close_wait遷移到last_ack,則系統(tǒng)中會存在很多close_wait狀態(tài)的連接,如下圖所示:
可能得原因如下:
1.關閉socket不及時:例如I/O線程被意外阻塞,或者I/O線程執(zhí)行的用戶自定義Task比例過高,導致I/O操作處理不及時,鏈路不能被及時釋放。
通常,CLOSE_WAIT 狀態(tài)在服務器停留時間很短,如果你發(fā)現(xiàn)大量的 CLOSE_WAIT 狀態(tài),那么就意味著被動關閉的一方?jīng)]有及時發(fā)出 FIN 包,一般有如下幾種可能
1.程序問題:如果代碼層面忘記了 close 相應的 socket 連接,那么自然不會發(fā)出 FIN 包,從而導致 CLOSE_WAIT 累積;或者代碼不嚴謹,出現(xiàn)死循環(huán)之類的問題,導致即便后面寫了 close 也永遠執(zhí)行不到。
2.響應太慢或者超時設置過小:如果連接雙方不和諧,一方不耐煩直接 timeout,另一方卻還在忙于耗時邏輯,就會導致 close 被延后。響應太慢是首要問題,不過換個角度看,也可能是 timeout 設置過小。
7.如果服務器上存在大量 TIME_WAIT 情況,如何改善?
過多的 TIME_WAIT 的主要危害有兩種:
第一是內存資源占用,這個目前看來不是太嚴重,基本可以忽略。
第二是對端口資源的占用,一個 TCP 連接至少消耗一個本地端口。要知道,端口資源也是有限的,一般可以開啟的端口為 32768~61000 ,也可以通過net.ipv4.ip_local_port_range指定,如果 TIME_WAIT 狀態(tài)過多,會導致無法創(chuàng)建新連接
如何優(yōu)化 TIME_WAIT?
1.net.ipv4.tcp_max_tw_buckets
一個暴力的方法是通過 sysctl 命令,將系統(tǒng)值調小。這個值默認為 18000,當系統(tǒng)中處于 TIME_WAIT 的連接一旦超過這個值時,系統(tǒng)就會將所有的 TIME_WAIT 連接狀態(tài)重置,并且只打印出警告信息。這個方法過于暴力,而且治標不治本,帶來的問題遠比解決的問題多,不推薦使用。
2.調低 TCP_TIMEWAIT_LEN,重新編譯系統(tǒng)
這個方法是一個不錯的方法,缺點是需要“一點”內核方面的知識,能夠重新編譯內核。我想這個不是大多數(shù)人能接受的方式。
3.SO_LINGER 的設置
英文單詞“l(fā)inger”的意思為停留,我們可以通過設置套接字選項,來設置調用 close 或者 shutdown 關閉連接時的行為。
設置 linger 參數(shù)有幾種可能:
1.如果l_onoff為 0,那么關閉本選項。l_linger的值被忽略,這對應了默認行為,close 或 shutdown 立即返回。如果在套接字發(fā)送緩沖區(qū)中有數(shù)據(jù)殘留,系統(tǒng)會將試著把這些數(shù)據(jù)發(fā)送出去。
2.如果l_onoff為非 0, 且l_linger值也為 0,那么調用 close 后,會立該發(fā)送一個 RST 標志給對端,該 TCP 連接將跳過四次揮手,也就跳過了 TIME_WAIT 狀態(tài),直接關閉。這種關閉的方式稱為“強行關閉”。 在這種情況下,排隊數(shù)據(jù)不會被發(fā)送,被動關閉方也不知道對端已經(jīng)徹底斷開。只有當被動關閉方正阻塞在recv()調用上時,接受到 RST 時,會立刻得到一個“connet reset by peer”的異常。
struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 0; setsockopt(s,SOL_SOCKET,SO_LINGER, &so_linger,sizeof(so_linger));3.如果l_onoff為非 0, 且l_linger的值也非 0,那么調用 close 后,調用 close 的線程就將阻塞,直到數(shù)據(jù)被發(fā)送出去,或者設置的l_linger計時時間到。
8.tcp和udp對比有什么區(qū)別?分別用在哪些場景?舉例說明
1.TCP?向連接(如打電話要先撥號建?連接); UDP是?連接的,即發(fā)送數(shù)據(jù)之前不需要建?連接。 2.TCP提供可靠的服務,通過TCP連接傳送的數(shù)據(jù),?差錯,不丟失,不重復,且按序到達; UDP盡最?努?交付,即不保證可靠交付。 3.Tcp通過校驗和,重傳控制,序號標識,滑動窗?、確認應答實現(xiàn)可靠傳輸。 如丟包時的重發(fā)控 制,還可以對次序亂掉的分包進?順序控制。 4.UDP具有較好的實時性,?作效率?TCP?,適?于對?速傳輸和實時性有較?的通信或?播通信。 5.每?條TCP連接只能是點到點的;UDP?持?對?,?對多,多對?和多對多的交互通信。 5.TCP對系統(tǒng)資源要求較多,UDP對系統(tǒng)資源要求較少。TCP 場景
1.遠程控制(SSH) 2.File Transfer Protocol(FTP) 3.郵件(SMTP、IMAP)等 4.點對點文件傳出(微信等)UDP 場景
1.網(wǎng)絡游戲 2.音視頻傳輸 3.DNS 4.Ping 5.直播模糊地帶(TCP、UDP 都可以考慮)
1.HTTP(目前以 TCP 為主) 2.文件傳輸總結:
1.UDP 的核心價值是靈活、輕量,構造了最小版本的傳輸層協(xié)議。
2.TCP 最核心的價值就是提供封裝好的一套解決可靠性的優(yōu)秀方案
TCP 幫助我們在確保吞吐量、延遲、丟包率的基礎上,保證可靠性。 UDP 則不同,UDP 提供了最小版的實現(xiàn),只支持Checksum。UDP 最核心的價值是靈活、輕量、傳輸速度快。
9.描述擁塞 控制的過程?
TCP 的擁塞控制就是在不堵塞,不丟包的情況下,盡量發(fā)揮帶寬,TCP 的擁塞控制主要來避免兩種現(xiàn)象,包丟失和超時重傳
水管有粗細,網(wǎng)絡有帶寬,也即每秒鐘能夠發(fā)送多少數(shù)據(jù);水管有長度,端到端有時延。在理想狀態(tài)下,水管里面水的量 = 水管粗細 x 水管長度。對于到網(wǎng)絡上,通道的容量 = 帶寬 × 往返延遲。
如果我們設置發(fā)送窗口,使得發(fā)送但未確認的包為為通道的容量,就能夠撐滿整個管道。
如圖所示,假設往返時間為 8s,去 4s,回 4s,每秒發(fā)送一個包,每個包 1024byte。已經(jīng)過去了 8s,則 8 個包都發(fā)出去了,其中前 4 個包已經(jīng)到達接收端,但是 ACK 還沒有返回,不能算發(fā)送成功。5-8 后四個包還在路上,還沒被接收。這個時候,整個管道正好撐滿,在發(fā)送端,已發(fā)送未確認的為 8 個包,正好等于帶寬,也即每秒發(fā)送 1 個包,乘以來回時間 8s。
如果我們在這個基礎上再調大窗口,使得單位時間內更多的包可以發(fā)送,會出現(xiàn)什么現(xiàn)象呢?
我們來想,原來發(fā)送一個包,從一端到達另一端,假設一共經(jīng)過四個設備,每個設備處理一個包時間耗費 1s,所以到達另一端需要耗費 4s,如果發(fā)送的更加快速,則單位時間內,會有更多的包到達這些中間設備,這些設備還是只能每秒處理一個包的話,多出來的包就會被丟棄,這是我們不想看到的。
這個時候,我們可以想其他的辦法,例如這個四個設備本來每秒處理一個包,但是我們在這些設備上加緩存,處理不過來的在隊列里面排著,這樣包就不會丟失,但是缺點是會增加時延,這個緩存的包,4s 肯定到達不了接收端了,如果時延達到一定程度,就會超時重傳,也是我們不想看到的。
于是 TCP 的擁塞控制主要來避免兩種現(xiàn)象,包丟失和超時重傳。一旦出現(xiàn)了這些現(xiàn)象就說明,發(fā)送速度太快了,要慢一點。但是一開始我怎么知道速度多快呢,我怎么知道應該把窗口調整到多大呢?
(1)慢啟動
如果我們通過漏斗往瓶子里灌水,我們就知道,不能一桶水一下子倒進去,肯定會濺出來,要一開始慢慢的倒,然后發(fā)現(xiàn)總能夠倒進去,就可以越倒越快。這叫作慢啟動。
一條 TCP 連接開始,cwnd 設置為一個報文段,一次只能發(fā)送一個;當收到這一個確認的時候,cwnd 加一,于是一次能夠發(fā)送兩個;當這兩個的確認到來的時候,每個確認 cwnd 加一,兩個確認 cwnd 加二,于是一次能夠發(fā)送四個;當這四個的確認到來的時候,每個確認 cwnd 加一,四個確認 cwnd 加四,于是一次能夠發(fā)送八個。可以看出這是指數(shù)性的增長。
漲到什么時候是個頭呢?有一個值 ssthresh 為 65535 個字節(jié),當超過這個值的時候,就要小心一點了,不能倒這么快了,可能快滿了,再慢下來。
每收到一個確認后,cwnd 增加 1/cwnd,我們接著上面的過程來,一次發(fā)送八個,當八個確認到來的時候,每個確認增加 1/8,八個確認一共 cwnd 增加 1,于是一次能夠發(fā)送九個,變成了線性增長。
但是線性增長還是增長,還是越來越多,直到有一天,水滿則溢,出現(xiàn)了擁塞,這時候一般就會一下子降低倒水的速度,等待溢出的水慢慢滲下去。
擁塞的一種表現(xiàn)形式是丟包,需要超時重傳,這個時候,將 sshresh 設為 cwnd/2,將 cwnd 設為 1,重新開始慢啟動。這真是一旦超時重傳,馬上回到解放前。但是這種方式太激進了,將一個高速的傳輸速度一下子停了下來,會造成網(wǎng)絡卡頓。
(2)快速重傳算法
當接收端發(fā)現(xiàn)丟了一個中間包的時候,發(fā)送三次前一個包的 ACK,于是發(fā)送端就會快速的重傳,不必等待超時再重傳。TCP 認為這種情況不嚴重,因為大部分沒丟,只丟了一小部分,cwnd 減半為 cwnd/2,然后 sshthresh = cwnd,當三個包返回的時候,cwnd = sshthresh + 3,也就是沒有一夜回到解放前,而是還在比較高的值,呈線性增長。
當接收端發(fā)現(xiàn)丟了一個中間包的時候,發(fā)送三次前一個包的 ACK,于是發(fā)送端就會快速的重傳,不必等待超時再重傳。TCP 認為這種情況不嚴重,因為大部分沒丟,只丟了一小部分,cwnd 減半為 cwnd/2,然后 sshthresh = cwnd,當三個包返回的時候,cwnd = sshthresh + 3,也就是沒有一夜回到解放前,而是還在比較高的值,呈線性增長。
就像前面說的一樣,正是這種知進退,使得時延很重要的情況下,反而降低了速度。但是如果你仔細想一下,TCP 的擁塞控制主要來避免的兩個現(xiàn)象都是有問題的。
第一個問題是丟包并不代表著通道滿了,也可能是管子本來就漏水。例如公網(wǎng)上帶寬不滿也會丟包,這個時候就認為擁塞了,退縮了,其實是不對的。
第二個問題是 TCP 的擁塞控制要等到將中間設備都填充滿了,才發(fā)生丟包,從而降低速度,這時候已經(jīng)晚了。其實 TCP 只要填滿管道就可以了,不應該接著填,直到連緩存也填滿。
為了優(yōu)化這兩個問題,后來有了TCP BBR 擁塞算法。它企圖找到一個平衡點,就是通過不斷的加快發(fā)送速度,將管道填滿,但是不要填滿中間設備的緩存,因為這樣時延會增加,在這個平衡點可以很好的達到高帶寬和低時延的平衡。
10.什么是nagle算法?使用時可能會有什么坑?
Nagle算法主要是避免發(fā)送小的數(shù)據(jù)包,要求TCP連接上最多只能有一個未被確認的小分組,在該分組的確認到達之前不能發(fā)送其他的小分組。相反,TCP收集這些少量的小分組,并在確認到來時以一個分組的方式發(fā)出去。
if there is new data to sendif the window size >= MSS and available data is >= MSSsend complete MSS segment nowelseif there is unconfirmed data still in the pipeenqueue data in the buffer until an acknowledge is receivedelsesend data immediatelyend ifend if end if從上述算法中看出:
對于MSS的片段直接發(fā)送
如果有沒有被確認的data在緩沖區(qū)內,先將待發(fā)送的數(shù)據(jù)放到buffer中直到被發(fā)送的數(shù)據(jù)被確認【最多只能有一個未被確認的小分組】
兩種情況置位,就直接發(fā)送數(shù)據(jù),實際上如果小包,但是沒有未被確認的分組,就直接發(fā)送數(shù)據(jù)。
這里通過一個實驗來看下Nagle算法對于發(fā)送的優(yōu)化:
實驗要求:Client端每次發(fā)送1個字節(jié),將hello發(fā)送到Server端,然后server再全部發(fā)送給Client,其實要點在于Client的發(fā)送,預期的結果是:
我們雖然一個字節(jié)一個字節(jié)的發(fā),但是在協(xié)議中使用Nagle算法,可能會有延時等待的狀況,即將幾個字符合成一個片段進行發(fā)送
必須是收到對方的確認之后,才能再次發(fā)送
看下實驗的結果:
從圖中的結果可以看出
HELLO 被分成 2個包發(fā)送了,應用層調用send 5次,由于Nagle算法,將ELLO合成一個包發(fā)送,這樣大可以減少Samll packet的數(shù)量,增加TCP傳輸?shù)男?/p>
分成的2個數(shù)據(jù)包,并沒有連續(xù)被發(fā)出,這也符合Nagle算法的原則,即TCP連接上最多只能有一個未被確認的小分組,等待收到ACK之后,才發(fā)第二個封包。
禁用Nagle算法:
在默認的情況下,Nagle算法是默認開啟的,Nagle算法比較適用于發(fā)送方發(fā)送大批量的小數(shù)據(jù),并且接收方作出及時回應的場合,這樣可以降低包的傳輸個數(shù)。同時協(xié)議也要求提供一個方法給上層來禁止掉Nagle算法
當你的應用不是連續(xù)請求+應答的模型的時候,而是需要實時的單項的發(fā)送數(shù)據(jù)并及時獲取響應,這種case就明顯不太適合Nagle算法,明顯有delay的。
linux提供了TCP_NODELAY的選項來禁用Nagle算法。
禁用方法:
來看下禁用后同樣發(fā)送Hello的實驗結果
從實驗結果中可以得出如下結論:
2.不用等待ACK,可以連續(xù)發(fā)送
Delay ACK and Nagle
Nagle指出Nagle算法與Delay ACK機制有共存的情況下會有一些非常糟糕的狀況,比如舉一個場景:PC1和PC2進行通信,PC1發(fā)數(shù)據(jù)給PC2,PC1使用Nagle算法,PC2有delay ACK機制
1. PC1發(fā)送一個數(shù)據(jù)包給PC2,PC2會先不回應,delay ACK 2. PC1再次調用send函數(shù)發(fā)送小于MSS的數(shù)據(jù),這些數(shù)據(jù)會被保存到Buffer中,等待ACK,才能再次被發(fā)送從上面的描述看,顯然已經(jīng)死鎖了,PC1在等待ACK,PC2在delay ACK,那么解鎖的代價就是Delay ACK的Timer到期,至少40ms[40ms~500ms不等],也就是2種算法在通信的時候,會產生不必要的延時!
可以看下實驗的圖示, 9包是發(fā)送H字符到server,可以看到隔了30ms的delay ack延時才等到數(shù)據(jù),發(fā)送一個DATA+ACK包,在這個時間段內其實也是用包發(fā)送的,但是nagle算法是要等待ACK的到來才能發(fā)包的,所以也會看到11號包要在ACK包之后。如果30ms延時仍然沒有數(shù)據(jù),就是我們上述說的那樣白白的等待一個delay ack超時。
如何來解決這種問題?
其實Nagle算法本身的立意是好的,避免網(wǎng)絡充斥著過多的小包,提高網(wǎng)絡傳輸?shù)男?#xff0c;同時Delay ACK也是為了提高TCP的性能,不過二者遇到了,就比較悲劇了。其實在RFC中已經(jīng)提供了一個用戶級別的解決方案,即避免 write–write–read的這種寫法,write–read–write–read 以及write–write–write都是OK的。假設這里有數(shù)據(jù)要發(fā)送,這個數(shù)據(jù)分為頭部和數(shù)據(jù)部分,2部分發(fā)送,然后再回讀響應,寫法如下
1.write(header)2.write(body)3.read(response)服務器read寫法如下1. read(request)2. process(request)3. write(response)應用程序使能了Nagle算法,第一個header是一定能夠發(fā)送出去的,因為前面沒有帶確認的數(shù)據(jù),服務器端接收到header之后,也發(fā)現(xiàn)是不完全的,還會再次等待request,同時要delay ACK,再次發(fā)write的時候,發(fā)現(xiàn)沒有ACK,也會等待ACK延遲發(fā)送。這樣只能超時才能再次傳輸。
這個問題的產生,主要是Nagle和delay ACK 副作用以及write write read的程式造成的。一般寫程序的時候不推薦這樣的寫法。如何解決? 可能想到的就是上面的禁止掉Nagle算法,這也是一種辦法,不過這種辦法同時也會讓網(wǎng)絡充斥小包,降低效率。對于應用程序來講,只要避免write-wirte-read的這種寫法就可以避免掉問題,比如write一塊去寫,一次寫成功,就一個包發(fā)過去了,就沒有等待delay的過程了!所以寫程序的時候還是要注意再注意。
11.http狀態(tài)碼301和302是代表什么?403和304代表什么?500,502,503,504分別代表什么?
12.HTTP中的keep-alive和TCP中keepalive又有什么區(qū)別?
(1)TCP : keepalive,保持活躍的機制
原理:
定義一個時間段,在這個時間段內,如果沒有任何連接相關的活動,TCP 保活機制會開始作用,每隔一個時間間隔,發(fā)送一個探測報文,該探測報文包含的數(shù)據(jù)非常少,如果連續(xù)幾個探測報文都沒有得到響應,則認為當前的 TCP 連接已經(jīng)死亡,系統(tǒng)內核將錯誤信息通知給上層應用程序。
上述的可定義變量,分別被稱為保活時間、保活時間間隔和保活探測次數(shù)。在 Linux 系統(tǒng)中,這些變量分別對應 sysctl 變量net.ipv4.tcp_keepalive_time、net.ipv4.tcp_keepalive_intvl、 net.ipv4.tcp_keepalve_probes,默認設置是 7200 秒(2 小時)、75 秒和 9 次探測。
如果開啟了 TCP 保活,需要考慮以下幾種情況:
1.第一種,對端程序是正常工作的。當 TCP 保活的探測報文發(fā)送給對端, 對端會正常響應,這樣 TCP 保活時間會被重置,等待下一個 TCP 保活時間的到來。
2.第二種,對端程序崩潰并重啟。當 TCP 保活的探測報文發(fā)送給對端后,對端是可以響應的,但由于沒有該連接的有效信息,會產生一個 RST 報文,這樣很快就會發(fā)現(xiàn) TCP 連接已經(jīng)被重置。
3.第三種,是對端程序崩潰,或對端由于其他原因導致報文不可達。當 TCP 保活的探測報文發(fā)送給對端后,石沉大海,沒有響應,連續(xù)幾次,達到保活探測次數(shù)后,TCP 會報告該 TCP 連接已經(jīng)死亡。
TCP 保活機制默認是關閉的,當我們選擇打開時,可以分別在連接的兩個方向上開啟,也可以單獨在一個方向上開啟。如果開啟服務器端到客戶端的檢測,就可以在客戶端非正常斷連的情況下清除在服務器端保留的“臟數(shù)據(jù)”;而開啟客戶端到服務器端的檢測,就可以在服務器無響應的情況下,重新發(fā)起連接。
(2)區(qū)別
1、TCP連接往往就是我們廣義理解上的長連接,因為它具備雙端連續(xù)收發(fā)報文的能力;開啟了keep-alive的HTTP連接,也是一種長連接,但是它由于協(xié)議本身的限制,服務端無法主動發(fā)起應用報文。
2、**TCP中的keepalive是用來保鮮、保活的;**HTTP中的keep-alive機制主要為了讓支撐它的TCP連接活的的更久,所以通常又叫做:HTTP persistent connection(持久連接) 和 HTTP connection reuse(連接重用)。
13.https握手的過程?
14.什么是httpdns?傳統(tǒng)dns有什么問題?
1.什么是httpdns
HTTPNDS 其實就是,不走傳統(tǒng)的 DNS 解析,而是自己搭建基于 HTTP 協(xié)議的 DNS 服務器集群,分布在多個地點和多個運營商。
當客戶端需要 DNS 解析的時候,直接通過 HTTP 協(xié)議進行請求這個服務器集群,得到就近的地址
2.傳統(tǒng)dns有什么問題?
2.1 域名緩存問題‘
它可以在本地做一個緩存,也就是說,不是每一個請求,它都會去訪問權威 DNS 服務器,而是訪問過一次就把結果緩存到自己本地,當其他人來問的時候,直接就返回這個緩存數(shù)據(jù)。
這就相當于導游去過一個飯店,自己腦子記住了地址,當有一個游客問的時候,他就憑記憶回答了,不用再去查地址簿。這樣經(jīng)常存在的一個問題是,人家那個飯店明明都已經(jīng)搬了,結果作為導游,他并沒有刷新這個緩存,結果你辛辛苦苦到了這個地點,發(fā)現(xiàn)飯店已經(jīng)變成了服裝店,你是不是會非常失望?
另外,有的運營商會把一些靜態(tài)頁面,緩存到本運營商的服務器內,這樣用戶請求的時候,就不用跨運營商進行訪問,這樣既加快了速度,也減少了運營商之間流量計算的成本。在域名解析的時候,不會將用戶導向真正的網(wǎng)站,而是指向這個緩存的服務器。
很多情況下是看不出問題的,但是當頁面更新,用戶會訪問到老的頁面,問題就出來了。例如,你聽說一個餐館推出了一個新菜,你想去嘗一下。結果導游告訴你,在這里吃也是一樣的。有的游客會覺得沒問題,但是對于想嘗試新菜的人來說,如果導游說帶你去,但其實并沒有吃到新菜,你是不是也會非常失望呢?
再就是本地的緩存,往往使得全局負載均衡失敗,因為上次進行緩存的時候,緩存中的地址不一定是這次訪問離客戶最近的地方,如果把這個地址返回給客戶,那肯定就會繞遠路。
就像上一次客戶要吃西湖醋魚的事,導游知道西湖邊有一家,因為當時游客就在西湖邊,可是,下一次客戶在靈隱寺,想吃西湖醋魚的時候,導游還指向西湖邊的那一家,那這就繞的太遠了。
2.2 域名轉發(fā)問題
緩存問題還是說本地域名解析服務,還是會去權威 DNS 服務器中查找,只不過不是每次都要查找。可以說這還是大導游、大中介。還有一些小導游、小中介,有了請求之后,直接轉發(fā)給其他運營商去做解析,自己只是外包了出去。
這樣的問題是,如果是 A 運營商的客戶,訪問自己運營商的 DNS 服務器,如果 A 運營商去權威 DNS 服務器查詢的話,權威 DNS 服務器知道你是 A 運營商的,就返回給一個部署在 A 運營商的網(wǎng)站地址,這樣針對相同運營商的訪問,速度就會快很多。
但是 A 運營商偷懶,將解析的請求轉發(fā)給 B 運營商,B 運營商去權威 DNS 服務器查詢的話,權威服務器會誤認為,你是 B 運營商的,那就返回給你一個在 B 運營商的網(wǎng)站地址吧,結果客戶的每次訪問都要跨運營商,速度就會很慢。
2.3 出口 NAT 問題
網(wǎng)關在出口的時候,很多機房都會配置NAT,也即網(wǎng)絡地址轉換,使得從這個網(wǎng)關出去的包,都換成新的 IP 地址,當然請求返回的時候,在這個網(wǎng)關,再將 IP 地址轉換回去,所以對于訪問來說是沒有任何問題。
但是一旦做了網(wǎng)絡地址的轉換,權威的 DNS 服務器,就沒辦法通過這個地址,來判斷客戶到底是來自哪個運營商,而且極有可能因為轉換過后的地址,誤判運營商,導致跨運營商的訪問。
2.4域名更新問題
本地 DNS 服務器是由不同地區(qū)、不同運營商獨立部署的。對域名解析緩存的處理上,實現(xiàn)策略也有區(qū)別,有的會偷懶,忽略域名解析結果的 TTL 時間限制,在權威 DNS 服務器解析變更的時候,解析結果在全網(wǎng)生效的周期非常漫長。但是有的時候,在 DNS 的切換中,場景對生效時間要求比較高。
例如雙機房部署的時候,跨機房的負載均衡和容災多使用 DNS 來做。當一個機房出問題之后,需要修改權威 DNS,將域名指向新的 IP 地址,但是如果更新太慢,那很多用戶都會出現(xiàn)訪問異常。
這就像,有的導游比較勤快、敬業(yè),時時刻刻關注酒店、餐館、交通的變化,問他的時候,往往會得到最新情況。有的導游懶一些,8 年前背的導游詞就沒換過,問他的時候,指的路往往就是錯的。
2.5解析延遲問題
DNS 的查詢過程需要遞歸遍歷多個 DNS 服務器,才能獲得最終的解析結果,這會帶來一定的時延,甚至會解析超時。
15.開放性問題:從網(wǎng)絡角度,如何優(yōu)化性能?
總結
以上是生活随笔為你收集整理的网络相关面试题(持续更新)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最大化参数 火车头_铁路大亨各火车头的性
- 下一篇: CS224n课程Assignment3参