TCP 三次握手就三個(gè)狀態(tài) :syn_sent挽懦、syn_rcv纺阔、established
一、客戶端的優(yōu)化
三次握手建立連接的首要目的是同步序列號(hào)。只有同步了序列號(hào)才有可靠的傳輸客年,TCP 協(xié)議的許多特性都是依賴序列號(hào)實(shí)現(xiàn)的,比如流量控制叮贩、消息丟失后的重發(fā)等等
客戶端在等待服務(wù)器回復(fù)的 ACK 報(bào)文几于。正常情況下,服務(wù)器會(huì)在幾毫秒內(nèi)返回 ACK筹陵,但如果客戶端遲遲沒(méi)有收到 ACK 會(huì)怎么樣呢刽锤?客戶端會(huì)重發(fā) SYN,重試的次數(shù)由tcp_syn_retries 參數(shù)控制朦佩,默認(rèn)是 6 次并思。
優(yōu)化:可以適當(dāng)調(diào)低重試次數(shù),盡快把錯(cuò)誤暴露給應(yīng)用程序语稠。
二宋彼、服務(wù)器端的優(yōu)化
在SYN_RCV(RCV 是 received 的縮寫(xiě))狀態(tài)下,服務(wù)器必須建立一個(gè) SYN 半連接隊(duì)列來(lái)維護(hù)未完成的握手信息仙畦,當(dāng)這個(gè)隊(duì)列溢出后输涕,服務(wù)器將無(wú)法再建立新連接。
新連接建立失敗的原因有很多议泵,怎樣獲得由于隊(duì)列已滿而引發(fā)的失敗次數(shù)呢占贫?netstat -s 命令給出的統(tǒng)計(jì)結(jié)果中可以得到隊(duì)列溢出導(dǎo)致 SYN 被丟棄的個(gè)數(shù)
優(yōu)化:調(diào)大 SYN 半連接隊(duì)列。
如果 SYN 半連接隊(duì)列已滿先口,只能丟棄連接嗎型奥?并不是這樣,開(kāi)啟 syncookies 功能就可以在不使用 SYN 隊(duì)列的情況下成功建立連接碉京。syncookies 是這么做的:服務(wù)器根據(jù)當(dāng)前狀態(tài)計(jì)算出一個(gè)值厢汹,放在己方發(fā)出的 SYN+ACK 報(bào)文中發(fā)出,當(dāng)客戶端返回 ACK 報(bào)文時(shí)谐宙,取出該值驗(yàn)證烫葬,如果合法,就認(rèn)為連接建立成功。
由于 syncookie 僅用于應(yīng)對(duì)SYN 泛洪攻擊(攻擊者惡意構(gòu)造大量的 SYN 報(bào)文發(fā)送給服務(wù)器搭综,造成 SYN 半連接隊(duì)列溢出垢箕,導(dǎo)致正常客戶端的連接無(wú)法建立)兑巾,這種方式建立的連接条获,許多 TCP 特性都無(wú)法使用。所以蒋歌,應(yīng)當(dāng)把 tcp_syncookies 設(shè)置為 1帅掘,僅在隊(duì)列滿時(shí)再啟用。
服務(wù)器收到 ACK 后連接建立成功堂油,此時(shí)修档,內(nèi)核會(huì)把連接從 SYN 半連接隊(duì)列中移出,再移入 accept 隊(duì)列府框,等待進(jìn)程調(diào)用 accept 函數(shù)時(shí)把連接取出來(lái)吱窝。如果進(jìn)程不能及時(shí)地調(diào)用accept 函數(shù),就會(huì)造成 accept 隊(duì)列溢出寓免,最終導(dǎo)致建立好的 TCP 連接被丟棄癣诱。
TFO 技術(shù)繞過(guò)三次握手,使得 HTTP 請(qǐng)求減少了 1 個(gè) RTT 的時(shí)間袜香。Linux 下可以通過(guò)tcp_fastopen 參數(shù)開(kāi)啟該功能撕予。