別搞混了!
時間:2021-08-19 16:30:42
手機(jī)看文章
掃描二維碼
隨時隨地手機(jī)看文章
[導(dǎo)讀]大家好,我是小林。之前有讀者問了我這么個問題:大致問題是,TCP的Keepalive和HTTP的Keep-Alive是一個東西嗎?這是個好問題,應(yīng)該有不少人都會搞混,因?yàn)檫@兩個東西看上去太像了,很容易誤以為是同一個東西。事實(shí)上,這兩個完全是兩樣不同東西,實(shí)現(xiàn)的層面也不同:HTTP...
大家好,我是小林。之前有讀者問了我這么個問題:大致問題是,TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一個東西嗎?這是個好問題,應(yīng)該有不少人都會搞混,因?yàn)檫@兩個東西看上去太像了,很容易誤以為是同一個東西。事實(shí)上,這兩個完全是兩樣不同東西,實(shí)現(xiàn)的層面也不同:
- HTTP 的 Keep-Alive,是由應(yīng)用層(用戶態(tài)) 實(shí)現(xiàn)的,稱為 HTTP 長連接;
- TCP 的 Keepalive,是由 TCP 層(內(nèi)核態(tài)) 實(shí)現(xiàn)的,稱為 TCP ?;顧C(jī)制;
HTTP 的 Keep-Alive
HTTP 協(xié)議采用的是「請求-應(yīng)答」的模式,也就是客戶端發(fā)起了請求,服務(wù)端才會返回響應(yīng),一來一回這樣子。由于 HTTP 是基于 TCP 傳輸協(xié)議實(shí)現(xiàn)的,客戶端與服務(wù)端要進(jìn)行 HTTP 通信前,需要先建立 TCP 連接,然后客戶端發(fā)送 HTTP ?請求,服務(wù)端收到后就返回響應(yīng),至此「請求-應(yīng)答」的模式就完成了,隨后就會釋放 TCP 連接。如果每次請求都要經(jīng)歷這樣的過程:建立 TCP -> 請求資源 -> 響應(yīng)資源 -> 釋放連接,那么此方式就是 HTTP 短連接,如下圖:這樣實(shí)在太累人了,一次連接只能請求一次資源。能不能在第一個 HTTP 請求完后,先不斷開 TCP 連接,讓后續(xù)的 HTTP 請求繼續(xù)使用此連接?當(dāng)然可以,HTTP 的 Keep-Alive 就是實(shí)現(xiàn)了這個功能,可以使用同一個 TCP 連接來發(fā)送和接收多個 HTTP 請求/應(yīng)答,避免了連接建立和釋放的開銷,這個方法稱為 HTTP 長連接。HTTP 長連接的特點(diǎn)是,只要任意一端沒有明確提出斷開連接,則保持 TCP 連接狀態(tài)。怎么才能使用 HTTP 的 Keep-Alive 功能?在 HTTP 1.0 中默認(rèn)是關(guān)閉的,如果瀏覽器要開啟 Keep-Alive,它必須在請求的包頭中添加:Connection:?Keep-Alive
然后當(dāng)服務(wù)器收到請求,作出回應(yīng)的時候,它也添加一個頭在響應(yīng)中:Connection:?Keep-Alive
這樣做,連接就不會中斷,而是保持連接。當(dāng)客戶端發(fā)送另一個請求時,它會使用同一個連接。這一直繼續(xù)到客戶端或服務(wù)器端提出斷開連接。從 HTTP 1.1 開始, 就默認(rèn)是開啟了 Keep-Alive,如果要關(guān)閉 Keep-Alive,需要在 HTTP 請求的包頭里添加:Connection:close
現(xiàn)在大多數(shù)瀏覽器都默認(rèn)是使用 HTTP/1.1,所以 Keep-Alive 都是默認(rèn)打開的。一旦客戶端和服務(wù)端達(dá)成協(xié)議,那么長連接就建立好了。HTTP 長連接不僅僅減少了 TCP 連接資源的開銷,而且這給 HTTP 流水線技術(shù)提供了可實(shí)現(xiàn)的基礎(chǔ)。所謂的 HTTP 流水線,是客戶端可以先一次性發(fā)送多個請求,而在發(fā)送過程中不需先等待服務(wù)器的回應(yīng),可以減少整體的響應(yīng)時間。舉例來說,客戶端需要請求兩個資源。以前的做法是,在同一個 TCP 連接里面,先發(fā)送 A 請求,然后等待服務(wù)器做出回應(yīng),收到后再發(fā)出 B 請求。HTTP 流水線機(jī)制則允許客戶端同時發(fā)出 A 請求和 B 請求。但是服務(wù)器還是按照順序響應(yīng),先回應(yīng) A 請求,完成后再回應(yīng) B 請求。而且要等服務(wù)器響應(yīng)完客戶端第一批發(fā)送的請求后,客戶端才能發(fā)出下一批的請求,也就說如果服務(wù)器響應(yīng)的過程發(fā)生了阻塞,那么客戶端就無法發(fā)出下一批的請求,此時就造成了「隊(duì)頭阻塞」的問題。可能有的同學(xué)會問,如果使用了 HTTP 長連接,如果客戶端完成一個 HTTP 請求后,就不再發(fā)起新的請求,此時這個 TCP 連接一直占用著不是挺浪費(fèi)資源的嗎?對沒錯,所以為了避免資源浪費(fèi)的情況,web 服務(wù)軟件一般都會提供 keepalive_timeout
參數(shù),用來指定 HTTP 長連接的超時時間。比如設(shè)置了 HTTP 長連接的超時時間是 60 秒,web 服務(wù)軟件就會啟動一個定時器,如果客戶端在完后一個 HTTP 請求后,在 60 秒內(nèi)都沒有再發(fā)起新的請求,定時器的時間一到,就會觸發(fā)回調(diào)函數(shù)來釋放該連接。TCP 的 Keepalive
TCP 的 Keepalive 這東西其實(shí)就是 TCP 的?;顧C(jī)制,它的工作原理我之前的文章寫過,這里就直接貼下以前的內(nèi)容。如果兩端的 TCP 連接一直沒有數(shù)據(jù)交互,達(dá)到了觸發(fā) TCP 保活機(jī)制的條件,那么內(nèi)核里的 TCP 協(xié)議棧就會發(fā)送探測報(bào)文。- 如果對端程序是正常工作的。當(dāng) TCP ?;畹奶綔y報(bào)文發(fā)送給對端, 對端會正常響應(yīng),這樣 TCP ?;顣r間會被重置,等待下一個 TCP ?;顣r間的到來。
- 如果對端主機(jī)崩潰,或?qū)Χ擞捎谄渌驅(qū)е聢?bào)文不可達(dá)。當(dāng) TCP ?;畹奶綔y報(bào)文發(fā)送給對端后,石沉大海,沒有響應(yīng),連續(xù)幾次,達(dá)到?;钐綔y次數(shù)后,TCP 會報(bào)告該 TCP 連接已經(jīng)死亡。
SO_KEEPALIVE
選項(xiàng)才能夠生效,如果沒有設(shè)置,那么就無法使用 TCP 保活機(jī)制。