国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀

這篇具有很好參考價值的文章主要介紹了Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀

前言

TCP 性能的提升不僅考察 TCP 的理論知識,還考察了對于操心系統(tǒng)提供的內(nèi)核參數(shù)的理解與應(yīng)用。

TCP 協(xié)議是由操作系統(tǒng)實現(xiàn),所以操作系統(tǒng)提供了不少調(diào)節(jié) TCP 的參數(shù)。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

如何正確有效的使用這些參數(shù),來提高 TCP 性能是一個不那么簡單事情。我們需要針對 TCP 每個階段的問題來對癥下藥,而不是病急亂投醫(yī)。

接下來,將以三個角度來闡述提升 TCP 的策略,分別是:

  • TCP 三次握手的性能提升;
  • TCP 四次揮手的性能提升;
  • TCP 數(shù)據(jù)傳輸?shù)男阅芴嵘?/li>

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

正文

01 TCP 三次握手的性能提升

TCP 是面向連接的、可靠的、雙向傳輸?shù)膫鬏攲油ㄐ艆f(xié)議,所以在傳輸數(shù)據(jù)之前需要經(jīng)過三次握手才能建立連接。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

那么,三次握手的過程在一個 HTTP 請求的平均時間占比 10% 以上,在網(wǎng)絡(luò)狀態(tài)不佳、高并發(fā)或者遭遇 SYN 攻擊等場景中,如果不能有效正確的調(diào)節(jié)三次握手中的參數(shù),就會對性能產(chǎn)生很多的影響。

如何正確有效的使用這些參數(shù),來提高 TCP 三次握手的性能,這就需要理解「三次握手的狀態(tài)變遷」,這樣當(dāng)出現(xiàn)問題時,先用?netstat?命令查看是哪個握手階段出現(xiàn)了問題,再來對癥下藥,而不是病急亂投醫(yī)。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

客戶端和服務(wù)端都可以針對三次握手優(yōu)化性能。主動發(fā)起連接的客戶端優(yōu)化相對簡單些,而服務(wù)端需要監(jiān)聽端口,屬于被動連接方,其間保持許多的中間狀態(tài),優(yōu)化方法相對復(fù)雜一些。

所以,客戶端(主動發(fā)起連接方)和服務(wù)端(被動連接方)優(yōu)化的方式是不同的,接下來分別針對客戶端和服務(wù)端優(yōu)化。

客戶端優(yōu)化

三次握手建立連接的首要目的是「同步序列號」。

只有同步了序列號才有可靠傳輸,TCP 許多特性都依賴于序列號實現(xiàn),比如流量控制、丟包重傳等,這也是三次握手中的報文稱為 SYN 的原因,SYN 的全稱就叫?Synchronize Sequence Numbers(同步序列號)。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

SYN_SENT 狀態(tài)的優(yōu)化

客戶端作為主動發(fā)起連接方,首先它將發(fā)送 SYN 包,于是客戶端的連接就會處于?SYN_SENT?狀態(tài)。

客戶端在等待服務(wù)端回復(fù)的 ACK 報文,正常情況下,服務(wù)器會在幾毫秒內(nèi)返回 SYN+ACK ,但如果客戶端長時間沒有收到 SYN+ACK 報文,則會重發(fā) SYN 包,重發(fā)的次數(shù)由 tcp_syn_retries 參數(shù)控制,默認是 5 次:

cat /proc/sys/net/ipv4/tcp_syn_retries

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

通常,第一次超時重傳是在 1 秒后,第二次超時重傳是在 2 秒,第三次超時重傳是在 4 秒后,第四次超時重傳是在 8 秒后,第五次是在超時重傳 16 秒后。沒錯,每次超時的時間是上一次的 2 倍。

當(dāng)?shù)谖宕纬瑫r重傳后,會繼續(xù)等待 32 秒,如果仍然服務(wù)端沒有回應(yīng) ACK,客戶端就會終止三次握手。

所以,總耗時是 1+2+4+8+16+32=63 秒,大約 1 分鐘左右。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

你可以根據(jù)網(wǎng)絡(luò)的穩(wěn)定性和目標服務(wù)器的繁忙程度修改 SYN 的重傳次數(shù),調(diào)整客戶端的三次握手時間上限。比如內(nèi)網(wǎng)中通訊時,就可以適當(dāng)調(diào)低重試次數(shù),盡快把錯誤暴露給應(yīng)用程序。

服務(wù)端優(yōu)化

當(dāng)服務(wù)端收到 SYN 包后,服務(wù)端會立馬回復(fù) SYN+ACK 包,表明確認收到了客戶端的序列號,同時也把自己的序列號發(fā)給對方。

此時,服務(wù)端出現(xiàn)了新連接,狀態(tài)是?SYN_RCV。在這個狀態(tài)下,Linux 內(nèi)核就會建立一個「半連接隊列」來維護「未完成」的握手信息,當(dāng)半連接隊列溢出后,服務(wù)端就無法再建立新的連接。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

SYN 攻擊,攻擊的是就是這個半連接隊列。

如何查看由于 SYN 半連接隊列已滿,而被丟棄連接的情況?

我們可以通過該?netstat -s?命令給出的統(tǒng)計結(jié)果中, 可以得到由于半連接隊列已滿,引發(fā)的失敗次數(shù):

netstat -s | grep "SYNs to LISTEN"

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

上面輸出的數(shù)值是累計值,表示共有多少個 TCP 連接因為半連接隊列溢出而被丟棄。隔幾秒執(zhí)行幾次,如果有上升的趨勢,說明當(dāng)前存在半連接隊列溢出的現(xiàn)象。

如何調(diào)整 SYN 半連接隊列大???

要想增大半連接隊列,不能只單純增大 tcp_max_syn_backlog 的值,還需一同增大 somaxconn 和 backlog,也就是增大 accept 隊列。否則,只單純增大 tcp_max_syn_backlog 是無效的。

增大 tcp_max_syn_backlog 和 somaxconn 的方法是修改 Linux 內(nèi)核參數(shù):

/proc/sys/net/ipv4/tcpmaxsyn_backlog

/proc/sys/net/core/somaxconn

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

增大 backlog 的方式,每個 Web 服務(wù)都不同,比如 Nginx 增大 backlog 的方法如下:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

最后,改變了如上這些參數(shù)后,要重啟 Nginx 服務(wù),因為 SYN 半連接隊列和 accept 隊列都是在?listen()?初始化的。

如果 SYN 半連接隊列已滿,只能丟棄連接嗎?

并不是這樣,開啟 syncookies 功能就可以在不使用 SYN 半連接隊列的情況下成功建立連接。

syncookies 的工作原理:服務(wù)器根據(jù)當(dāng)前狀態(tài)計算出一個值,放在己方發(fā)出的 SYN+ACK 報文中發(fā)出,當(dāng)客戶端返回 ACK 報文時,取出該值驗證,如果合法,就認為連接建立成功,如下圖所示。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

syncookies 參數(shù)主要有以下三個值:

  • 0 值,表示關(guān)閉該功能;
  • 1 值,表示僅當(dāng) SYN 半連接隊列放不下時,再啟用它;
  • 2 值,表示無條件開啟功能;

那么在應(yīng)對 SYN 攻擊時,只需要設(shè)置為 1 即可:

/proc/sys/net/ipv4/tcp_syncookies

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

SYN_RCV 狀態(tài)的優(yōu)化

當(dāng)客戶端接收到服務(wù)器發(fā)來的 SYN+ACK 報文后,就會回復(fù) ACK 給服務(wù)器,同時客戶端連接狀態(tài)從 SYN_SENT 轉(zhuǎn)換為 ESTABLISHED,表示連接建立成功。

服務(wù)器端連接成功建立的時間還要再往后,等到服務(wù)端收到客戶端的 ACK 后,服務(wù)端的連接狀態(tài)才變?yōu)?ESTABLISHED。

如果服務(wù)器沒有收到 ACK,就會重發(fā) SYN+ACK 報文,同時一直處于 SYN_RCV 狀態(tài)。

當(dāng)網(wǎng)絡(luò)繁忙、不穩(wěn)定時,報文丟失就會變嚴重,此時應(yīng)該調(diào)大重發(fā)次數(shù)。反之則可以調(diào)小重發(fā)次數(shù)。修改重發(fā)次數(shù)的方法是,調(diào)整 tcp_synack_retries 參數(shù):

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

tcp_synack_retries 的默認重試次數(shù)是 5 次,與客戶端重傳 SYN 類似,它的重傳會經(jīng)歷 1、2、4、8、16 秒,最后一次重傳后會繼續(xù)等待 32 秒,如果服務(wù)端仍然沒有收到 ACK,才會關(guān)閉連接,故共需要等待 63 秒。

服務(wù)器收到 ACK 后連接建立成功,此時,內(nèi)核會把連接從半連接隊列移除,然后創(chuàng)建新的完全的連接,并將其添加到 accept 隊列,等待進程調(diào)用 accept 函數(shù)時把連接取出來。

如果進程不能及時地調(diào)用 accept 函數(shù),就會造成 accept 隊列(也稱全連接隊列)溢出,最終導(dǎo)致建立好的 TCP 連接被丟棄。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

accept 隊列已滿,只能丟棄連接嗎?

丟棄連接只是 Linux 的默認行為,我們還可以選擇向客戶端發(fā)送 RST 復(fù)位報文,告訴客戶端連接已經(jīng)建立失敗。打開這一功能需要將 tcp_abort_on_overflow 參數(shù)設(shè)置為 1。

cat /proc/sys/net/ipv4/tcp_abort_on_overflow

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

tcp_abort_on_overflow 共有兩個值分別是 0 和 1,其分別表示:

  • 0 :如果 accept 隊列滿了,那么 server 扔掉 client 發(fā)過來的 ack ;
  • 1 :如果 accept 隊列滿了,server 發(fā)送一個?RST?包給 client,表示廢掉這個握手過程和這個連接;

如果要想知道客戶端連接不上服務(wù)端,是不是服務(wù)端 TCP 全連接隊列滿的原因,那么可以把 tcp_abort_on_overflow 設(shè)置為 1,這時如果在客戶端異常中可以看到很多?connection reset by peer的錯誤,那么就可以證明是由于服務(wù)端 TCP 全連接隊列溢出的問題。

通常情況下,應(yīng)當(dāng)把 tcp_abort_on_overflow 設(shè)置為 0,因為這樣更有利于應(yīng)對突發(fā)流量。

舉個例子,當(dāng) accept 隊列滿導(dǎo)致服務(wù)器丟掉了 ACK,與此同時,客戶端的連接狀態(tài)卻是 ESTABLISHED,客戶端進程就在建立好的連接上發(fā)送請求。只要服務(wù)器沒有為請求回復(fù) ACK,客戶端的請求就會被多次「重發(fā)」。如果服務(wù)器上的進程只是短暫的繁忙造成 accept 隊列滿,那么當(dāng) accept 隊列有空位時,再次接收到的請求報文由于含有 ACK,仍然會觸發(fā)服務(wù)器端成功建立連接。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

所以,tcp_abort_on_overflow 設(shè)為 0 可以提高連接建立的成功率,只有你非常肯定 TCP 全連接隊列會長期溢出時,才能設(shè)置為 1 以盡快通知客戶端。

如何調(diào)整 accept 隊列的長度呢?

accept 隊列的長度取決于 somaxconn 和 backlog 之間的最小值,也就是 min(somaxconn, backlog),其中:

  • somaxconn 是 Linux 內(nèi)核的參數(shù),默認值是 128,可以通過?net.core.somaxconn?來設(shè)置其值;
  • backlog 是?listen(int sockfd, int backlog)?函數(shù)中的 backlog 大??;

Tomcat、Nginx、Apache 常見的 Web 服務(wù)的 backlog 默認值都是 511。

如何查看服務(wù)端進程 accept 隊列的長度?

可以通過?ss -ltn?命令查看:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

  • Recv-Q:當(dāng)前 accept 隊列的大小,也就是當(dāng)前已完成三次握手并等待服務(wù)端?accept()?的 TCP 連接;
  • Send-Q:accept 隊列最大長度,上面的輸出結(jié)果說明監(jiān)聽 8088 端口的 TCP 服務(wù),accept 隊列的最大長度為 128;
如何查看由于 accept 連接隊列已滿,而被丟棄的連接?

當(dāng)超過了 accept 連接隊列,服務(wù)端則會丟掉后續(xù)進來的 TCP 連接,丟掉的 TCP 連接的個數(shù)會被統(tǒng)計起來,我們可以使用 netstat -s 命令來查看:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

上面看到的 41150 times ,表示 accept 隊列溢出的次數(shù),注意這個是累計值??梢愿魩酌腌妶?zhí)行下,如果這個數(shù)字一直在增加的話,說明 accept 連接隊列偶爾滿了。

如果持續(xù)不斷地有連接因為 accept 隊列溢出被丟棄,就應(yīng)該調(diào)大 backlog 以及 somaxconn 參數(shù)。

如何繞過三次握手?

以上我們只是在對三次握手的過程進行優(yōu)化,接下來我們看看如何繞過三次握手發(fā)送數(shù)據(jù)。

三次握手建立連接造成的后果就是,HTTP 請求必須在一個 RTT(從客戶端到服務(wù)器一個往返的時間)后才能發(fā)送。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

在 Linux 3.7 內(nèi)核版本之后,提供了 TCP Fast Open 功能,這個功能可以減少 TCP 連接建立的時延。

接下來說說,TCP Fast Open 功能的工作方式。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

在客戶端首次建立連接時的過程:

  1. 客戶端發(fā)送 SYN 報文,該報文包含 Fast Open 選項,且該選項的 Cookie 為空,這表明客戶端請求 Fast Open Cookie;
  2. 支持 TCP Fast Open 的服務(wù)器生成 Cookie,并將其置于 SYN-ACK 數(shù)據(jù)包中的 Fast Open 選項以發(fā)回客戶端;
  3. 客戶端收到 SYN-ACK 后,本地緩存 Fast Open 選項中的 Cookie。

所以,第一次發(fā)起 HTTP GET 請求的時候,還是需要正常的三次握手流程。

之后,如果客戶端再次向服務(wù)器建立連接時的過程:

  1. 客戶端發(fā)送 SYN 報文,該報文包含「數(shù)據(jù)」(對于非 TFO 的普通 TCP 握手過程,SYN 報文中不包含「數(shù)據(jù)」)以及此前記錄的 Cookie;
  2. 支持 TCP Fast Open 的服務(wù)器會對收到 Cookie 進行校驗:如果 Cookie 有效,服務(wù)器將在 SYN-ACK 報文中對 SYN 和「數(shù)據(jù)」進行確認,服務(wù)器隨后將「數(shù)據(jù)」遞送至相應(yīng)的應(yīng)用程序;如果 Cookie 無效,服務(wù)器將丟棄 SYN 報文中包含的「數(shù)據(jù)」,且其隨后發(fā)出的 SYN-ACK 報文將只確認 SYN 的對應(yīng)序列號;
  3. 如果服務(wù)器接受了 SYN 報文中的「數(shù)據(jù)」,服務(wù)器可在握手完成之前發(fā)送「數(shù)據(jù)」,這就減少了握手帶來的 1 個 RTT 的時間消耗;
  4. 客戶端將發(fā)送 ACK 確認服務(wù)器發(fā)回的 SYN 以及「數(shù)據(jù)」,但如果客戶端在初始的 SYN 報文中發(fā)送的「數(shù)據(jù)」沒有被確認,則客戶端將重新發(fā)送「數(shù)據(jù)」;
  5. 此后的 TCP 連接的數(shù)據(jù)傳輸過程和非 TFO 的正常情況一致。

所以,之后發(fā)起 HTTP GET 請求的時候,可以繞過三次握手,這就減少了握手帶來的 1 個 RTT 的時間消耗。

注:客戶端在請求并存儲了 Fast Open Cookie 之后,可以不斷重復(fù) TCP Fast Open 直至服務(wù)器認為 Cookie 無效(通常為過期)。

Linux 下怎么打開 TCP Fast Open 功能呢?

在 Linux 系統(tǒng)中,可以通過設(shè)置 tcp_fastopn 內(nèi)核參數(shù),來打開 Fast Open 功能:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

tcp_fastopn 各個值的意義:

  • 0 關(guān)閉
  • 1 作為客戶端使用 Fast Open 功能
  • 2 作為服務(wù)端使用 Fast Open 功能
  • 3 無論作為客戶端還是服務(wù)器,都可以使用 Fast Open 功能

TCP Fast Open 功能需要客戶端和服務(wù)端同時支持,才有效果。

小結(jié)

本小結(jié)主要介紹了關(guān)于優(yōu)化 TCP 三次握手的幾個 TCP 參數(shù)。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

客戶端的優(yōu)化

當(dāng)客戶端發(fā)起 SYN 包時,可以通過?tcp_syn_retries?控制其重傳的次數(shù)。

服務(wù)端的優(yōu)化

當(dāng)服務(wù)端 SYN 半連接隊列溢出后,會導(dǎo)致后續(xù)連接被丟棄,可以通過?netstat -s?觀察半連接隊列溢出的情況,如果 SYN 半連接隊列溢出情況比較嚴重,可以通過?tcp_max_syn_backlog、somaxconn、backlog參數(shù)來調(diào)整 SYN 半連接隊列的大小。

服務(wù)端回復(fù) SYN+ACK 的重傳次數(shù)由?tcp_synack_retries?參數(shù)控制。如果遭受 SYN 攻擊,應(yīng)把?tcp_syncookies?參數(shù)設(shè)置為 1,表示僅在 SYN 隊列滿后開啟 syncookie 功能,可以保證正常的連接成功建立。

服務(wù)端收到客戶端返回的 ACK,會把連接移入 accpet 隊列,等待進行調(diào)用 accpet() 函數(shù)取出連接。

可以通過?ss -lnt?查看服務(wù)端進程的 accept 隊列長度,如果 accept 隊列溢出,系統(tǒng)默認丟棄 ACK,如果可以把?tcp_abort_on_overflow?設(shè)置為 1 ,表示用 RST 通知客戶端連接建立失敗。

如果 accpet 隊列溢出嚴重,可以通過 listen 函數(shù)的?backlog?參數(shù)和?somaxconn?系統(tǒng)參數(shù)提高隊列大小,accept 隊列長度取決于 min(backlog, somaxconn)。

繞過三次握手

TCP Fast Open 功能可以繞過三次握手,使得 HTTP 請求減少了 1 個 RTT 的時間,Linux 下可以通過?tcp_fastopen?開啟該功能,同時必須保證服務(wù)端和客戶端同時支持。


02 TCP 四次揮手的性能提升

接下來,我們一起看看針對 TCP 四次揮手關(guān)不連接時,如何優(yōu)化性能。

在開始之前,我們得先了解四次揮手狀態(tài)變遷的過程。

客戶端和服務(wù)端雙方都可以主動斷開連接,通常先關(guān)閉連接的一方稱為主動方,后關(guān)閉連接的一方稱為被動方。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

可以看到,四次揮手過程只涉及了兩種報文,分別是 FIN 和 ACK:

  • FIN 就是結(jié)束連接的意思,誰發(fā)出 FIN 報文,就表示它將不會再發(fā)送任何數(shù)據(jù),關(guān)閉這一方向上的傳輸通道;
  • ACK 就是確認的意思,用來通知對方:你方的發(fā)送通道已經(jīng)關(guān)閉;

四次揮手的過程:

  • 當(dāng)主動方關(guān)閉連接時,會發(fā)送 FIN 報文,此時發(fā)送方的 TCP 連接將從 ESTABLISHED 變成 FIN_WAIT1。
  • 當(dāng)被動方收到 FIN 報文后,內(nèi)核會自動回復(fù) ACK 報文,連接狀態(tài)將從 ESTABLISHED 變成 CLOSE_WAIT,表示被動方在等待進程調(diào)用 close 函數(shù)關(guān)閉連接。
  • 當(dāng)主動方收到這個 ACK 后,連接狀態(tài)由 FIN_WAIT1 變?yōu)?FIN_WAIT2,也就是表示主動方的發(fā)送通道就關(guān)閉了。
  • 當(dāng)被動方進入 CLOSE_WAIT 時,被動方還會繼續(xù)處理數(shù)據(jù),等到進程的 read 函數(shù)返回 0 后,應(yīng)用程序就會調(diào)用 close 函數(shù),進而觸發(fā)內(nèi)核發(fā)送 FIN 報文,此時被動方的連接狀態(tài)變?yōu)?LAST_ACK。
  • 當(dāng)主動方收到這個 FIN 報文后,內(nèi)核會回復(fù) ACK 報文給被動方,同時主動方的連接狀態(tài)由 FIN_WAIT2 變?yōu)?TIME_WAIT,在 Linux 系統(tǒng)下大約等待 1 分鐘后,TIME_WAIT 狀態(tài)的連接才會徹底關(guān)閉。
  • 當(dāng)被動方收到最后的 ACK 報文后,被動方的連接就會關(guān)閉。

你可以看到,每個方向都需要一個 FIN 和一個 ACK,因此通常被稱為四次揮手。

這里一點需要注意是:主動關(guān)閉連接的,才有 TIME_WAIT 狀態(tài)。

主動關(guān)閉方和被動關(guān)閉方優(yōu)化的思路也不同,接下來分別說說如何優(yōu)化他們。

主動方的優(yōu)化

關(guān)閉的連接的方式通常有兩種,分別是 RST 報文關(guān)閉和 FIN 報文關(guān)閉。

如果進程異常退出了,內(nèi)核就會發(fā)送 RST 報文來關(guān)閉,它可以不走四次揮手流程,是一個暴力關(guān)閉連接的方式。

安全關(guān)閉連接的方式必須通過四次揮手,它由進程調(diào)用?close?和?shutdown?函數(shù)發(fā)起 FIN 報文(shutdown 參數(shù)須傳入 SHUT_WR 或者 SHUT_RDWR 才會發(fā)送 FIN)。

調(diào)用 close 函數(shù) 和 shutdown 函數(shù)有什么區(qū)別?

調(diào)用了 close 函數(shù)意味著完全斷開連接,完全斷開不僅指無法傳輸數(shù)據(jù),而且也不能發(fā)送數(shù)據(jù)。 此時,調(diào)用了 close 函數(shù)的一方的連接叫做「孤兒連接」,如果你用 netstat -p 命令,會發(fā)現(xiàn)連接對應(yīng)的進程名為空。

使用 close 函數(shù)關(guān)閉連接是不優(yōu)雅的。于是,就出現(xiàn)了一種優(yōu)雅關(guān)閉連接的?shutdown?函數(shù),它可以控制只關(guān)閉一個方向的連接:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

第二個參數(shù)決定斷開連接的方式,主要有以下三種方式:

  • SHUT_RD(0):關(guān)閉連接的「讀」這個方向,如果接收緩沖區(qū)有已接收的數(shù)據(jù),則將會被丟棄,并且后續(xù)再收到新的數(shù)據(jù),會對數(shù)據(jù)進行 ACK,然后悄悄地丟棄。也就是說,對端還是會接收到 ACK,在這種情況下根本不知道數(shù)據(jù)已經(jīng)被丟棄了。
  • SHUT_WR(1):關(guān)閉連接的「寫」這個方向,這就是常被稱為「半關(guān)閉」的連接。如果發(fā)送緩沖區(qū)還有未發(fā)送的數(shù)據(jù),將被立即發(fā)送出去,并發(fā)送一個 FIN 報文給對端。
  • SHUT_RDWR(2):相當(dāng)于 SHUT_RD 和 SHUT_WR 操作各一次,關(guān)閉套接字的讀和寫兩個方向。

close 和 shutdown 函數(shù)都可以關(guān)閉連接,但這兩種方式關(guān)閉的連接,不只功能上有差異,控制它們的 Linux 參數(shù)也不相同。

FIN_WAIT1 狀態(tài)的優(yōu)化

主動方發(fā)送 FIN 報文后,連接就處于 FIN_WAIT1 狀態(tài),正常情況下,如果能及時收到被動方的 ACK,則會很快變?yōu)?FIN_WAIT2 狀態(tài)。

但是當(dāng)遲遲收不到對方返回的 ACK 時,連接就會一直處于 FIN_WAIT1 狀態(tài)。此時,內(nèi)核會定時重發(fā) FIN 報文,其中重發(fā)次數(shù)由 tcp_orphan_retries 參數(shù)控制(注意,orphan 雖然是孤兒的意思,該參數(shù)卻不只對孤兒連接有效,事實上,它對所有 FIN_WAIT1 狀態(tài)下的連接都有效),默認值是 0。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

你可能會好奇,這 0 表示幾次?實際上當(dāng)為 0 時,特指 8 次,從下面的內(nèi)核源碼可知:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

如果 FIN_WAIT1 狀態(tài)連接很多,我們就需要考慮降低 tcp_orphan_retries 的值,當(dāng)重傳次數(shù)超過 tcp_orphan_retries 時,連接就會直接關(guān)閉掉。

對于普遍正常情況時,調(diào)低 tcp_orphan_retries 就已經(jīng)可以了。如果遇到惡意攻擊,F(xiàn)IN 報文根本無法發(fā)送出去,這由 TCP 兩個特性導(dǎo)致的:

  • 首先,TCP 必須報文報文是有序發(fā)送的,F(xiàn)IN 報文也不例外,當(dāng)發(fā)送緩沖區(qū)還有數(shù)據(jù)沒有發(fā)送時,F(xiàn)IN 報文也不能提前發(fā)送。
  • 其次,TCP 有流量控制功能,當(dāng)接收方接收窗口為 0 時,發(fā)送方就不能再發(fā)送數(shù)據(jù)。所以,當(dāng)攻擊者下載大文件時,就可以通過接收窗口設(shè)為 0 ,這就會使得 FIN 報文都無法發(fā)送出去,那么連接會一直處于 FIN_WAIT1 狀態(tài)。

解決這種問題的方法,是調(diào)整 tcp_max_orphans 參數(shù),它定義了「孤兒連接」的最大數(shù)量:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

當(dāng)進程調(diào)用了?close?函數(shù)關(guān)閉連接,此時連接就會是「孤兒連接」,因為它無法在發(fā)送和接收數(shù)據(jù)。Linux 系統(tǒng)為了防止孤兒連接過多,導(dǎo)致系統(tǒng)資源長時間被占用,就提供了?tcp_max_orphans?參數(shù)。如果孤兒連接數(shù)量大于它,新增的孤兒連接將不再走四次揮手,而是直接發(fā)送 RST 復(fù)位報文強制關(guān)閉。

FIN_WAIT2 狀態(tài)的優(yōu)化

當(dāng)主動方收到 ACK 報文后,會處于 FIN_WAIT2 狀態(tài),就表示主動方的發(fā)送通道已經(jīng)關(guān)閉,接下來將等待對方發(fā)送 FIN 報文,關(guān)閉對方的發(fā)送通道。

這時,如果連接是用 shutdown 函數(shù)關(guān)閉的,連接可以一直處于 FIN_WAIT2 狀態(tài),因為它可能還可以發(fā)送或接收數(shù)據(jù)。但對于 close 函數(shù)關(guān)閉的孤兒連接,由于無法在發(fā)送和接收數(shù)據(jù),所以這個狀態(tài)不可以持續(xù)太久,而 tcp_fin_timeout 控制了這個狀態(tài)下連接的持續(xù)時長,默認值是 60 秒:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

它意味著對于孤兒連接(調(diào)用 close 關(guān)閉的連接),如果在 60 秒后還沒有收到 FIN 報文,連接就會直接關(guān)閉。

這個 60 秒不是隨便決定的,它與 TIME_WAIT 狀態(tài)持續(xù)的時間是相同的,后面我們在來說說為什么是 60 秒。

TIME_WAIT 狀態(tài)的優(yōu)化

TIME_WAIT 是主動方四次揮手的最后一個狀態(tài),也是最常遇見的狀態(tài)。

當(dāng)收到被動方發(fā)來的 FIN 報文后,主動方會立刻回復(fù) ACK,表示確認對方的發(fā)送通道已經(jīng)關(guān)閉,接著就處于 TIME_WAIT 狀態(tài)。在 Linux 系統(tǒng),TIME_WAIT 狀態(tài)會持續(xù) 60 秒后才會進入關(guān)閉狀態(tài)。

TIME_WAIT 狀態(tài)的連接,在主動方看來確實快已經(jīng)關(guān)閉了。然后,被動方?jīng)]有收到 ACK 報文前,還是處于 LAST_ACK 狀態(tài)。如果這個 ACK 報文沒有到達被動方,被動方就會重發(fā) FIN 報文。重發(fā)次數(shù)仍然由前面介紹過的 tcp_orphan_retries 參數(shù)控制。

TIME-WAIT 的狀態(tài)尤其重要,主要是兩個原因:

  • 防止具有相同「四元組」的「舊」數(shù)據(jù)包被收到;
  • 保證「被動關(guān)閉連接」的一方能被正確的關(guān)閉,即保證最后的 ACK 能讓被動關(guān)閉方接收,從而幫助其正常關(guān)閉;

原因一:防止舊連接的數(shù)據(jù)包

TIME-WAIT 的一個作用是防止收到歷史數(shù)據(jù),從而導(dǎo)致數(shù)據(jù)錯亂的問題。

假設(shè) TIME-WAIT 沒有等待時間或時間過短,被延遲的數(shù)據(jù)包抵達后會發(fā)生什么呢?

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

  • 如上圖黃色框框服務(wù)端在關(guān)閉連接之前發(fā)送的?SEQ = 301?報文,被網(wǎng)絡(luò)延遲了。
  • 這時有相同端口的 TCP 連接被復(fù)用后,被延遲的?SEQ = 301?抵達了客戶端,那么客戶端是有可能正常接收這個過期的報文,這就會產(chǎn)生數(shù)據(jù)錯亂等嚴重的問題。

所以,TCP 就設(shè)計出了這么一個機制,經(jīng)過?2MSL?這個時間,足以讓兩個方向上的數(shù)據(jù)包都被丟棄,使得原來連接的數(shù)據(jù)包在網(wǎng)絡(luò)中都自然消失,再出現(xiàn)的數(shù)據(jù)包一定都是新建立連接所產(chǎn)生的。

原因二:保證連接正確關(guān)閉

TIME-WAIT 的另外一個作用是等待足夠的時間以確保最后的 ACK 能讓被動關(guān)閉方接收,從而幫助其正常關(guān)閉。

假設(shè) TIME-WAIT 沒有等待時間或時間過短,斷開連接會造成什么問題呢?

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

  • 如上圖紅色框框客戶端四次揮手的最后一個?ACK?報文如果在網(wǎng)絡(luò)中被丟失了,此時如果客戶端?TIME-WAIT?過短或沒有,則就直接進入了?CLOSE?狀態(tài)了,那么服務(wù)端則會一直處在?LASE-ACK?狀態(tài)。
  • 當(dāng)客戶端發(fā)起建立連接的?SYN?請求報文后,服務(wù)端會發(fā)送?RST?報文給客戶端,連接建立的過程就會被終止。

我們再回過頭來看看,為什么 TIME_WAIT 狀態(tài)要保持 60 秒呢?這與孤兒連接 FIN_WAIT2 狀態(tài)默認保留 60 秒的原理是一樣的,因為這兩個狀態(tài)都需要保持 2MSL 時長。MSL 全稱是 Maximum Segment Lifetime,它定義了一個報文在網(wǎng)絡(luò)中的最長生存時間(報文每經(jīng)過一次路由器的轉(zhuǎn)發(fā),IP 頭部的 TTL 字段就會減 1,減到 0 時報文就被丟棄,這就限制了報文的最長存活時間)。

為什么是 2 MSL 的時長呢?這其實是相當(dāng)于至少允許報文丟失一次。比如,若 ACK 在一個 MSL 內(nèi)丟失,這樣被動方重發(fā)的 FIN 會在第 2 個 MSL 內(nèi)到達,TIME_WAIT 狀態(tài)的連接可以應(yīng)對。

為什么不是 4 或者 8 MSL 的時長呢?你可以想象一個丟包率達到百分之一的糟糕網(wǎng)絡(luò),連續(xù)兩次丟包的概率只有萬分之一,這個概率實在是太小了,忽略它比解決它更具性價比。

因此,TIME_WAIT 和 FIN_WAIT2 狀態(tài)的最大時長都是 2 MSL,由于在 Linux 系統(tǒng)中,MSL 的值固定為 30 秒,所以它們都是 60 秒。

雖然 TIME_WAIT 狀態(tài)有存在的必要,但它畢竟會消耗系統(tǒng)資源。如果發(fā)起連接一方的 TIME_WAIT 狀態(tài)過多,占滿了所有端口資源,則會導(dǎo)致無法創(chuàng)建新連接。

  • 客戶端受端口資源限制:如果客戶端 TIME_WAIT 過多,就會導(dǎo)致端口資源被占用,因為端口就65536個,被占滿就會導(dǎo)致無法創(chuàng)建新的連接;
  • 服務(wù)端受系統(tǒng)資源限制:由于一個 四元組表示TCP連接,理論上服務(wù)端可以建立很多連接,服務(wù)端確實只監(jiān)聽一個端口 但是會把連接扔給處理線程,所以理論上監(jiān)聽的端口可以繼續(xù)監(jiān)聽。但是線程池處理不了那么多一直不斷的連接了。所以當(dāng)服務(wù)端出現(xiàn)大量 TIME_WAIT 時,系統(tǒng)資源被占滿時,會導(dǎo)致處理不過來新的連接;

另外,Linux 提供了 tcp_max_tw_buckets 參數(shù),當(dāng) TIME_WAIT 的連接數(shù)量超過該參數(shù)時,新關(guān)閉的連接就不再經(jīng)歷 TIME_WAIT 而直接關(guān)閉:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

當(dāng)服務(wù)器的并發(fā)連接增多時,相應(yīng)地,同時處于 TIME_WAIT 狀態(tài)的連接數(shù)量也會變多,此時就應(yīng)當(dāng)調(diào)大?tcp_max_tw_buckets?參數(shù),減少不同連接間數(shù)據(jù)錯亂的概率。

tcp_max_tw_buckets 也不是越大越好,畢竟內(nèi)存和端口都是有限的。

有一種方式可以在建立新連接時,復(fù)用處于 TIME_WAIT 狀態(tài)的連接,那就是打開 tcp_tw_reuse 參數(shù)。但是需要注意,該參數(shù)是只用于客戶端(建立連接的發(fā)起方),因為是在調(diào)用 connect() 時起作用的,而對于服務(wù)端(被動連接方)是沒有用的。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

tcp_tw_reuse 從協(xié)議角度理解是安全可控的,可以復(fù)用處于 TIME_WAIT 的端口為新的連接所用。

什么是協(xié)議角度理解的安全可控呢?主要有兩點:

  • 只適用于連接發(fā)起方,也就是 C/S 模型中的客戶端;
  • 對應(yīng)的 TIME_WAIT 狀態(tài)的連接創(chuàng)建時間超過 1 秒才可以被復(fù)用。

使用這個選項,還有一個前提,需要打開對 TCP 時間戳的支持(對方也要打開 ):

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

由于引入了時間戳,它能帶來了些好處:

  • 我們在前面提到的 2MSL 問題就不復(fù)存在了,因為重復(fù)的數(shù)據(jù)包會因為時間戳過期被自然丟棄;
  • 同時,它還可以防止序列號繞回,也是因為重復(fù)的數(shù)據(jù)包會由于時間戳過期被自然丟棄;

老版本的 Linux 還提供了 tcp_tw_recycle 參數(shù),但是當(dāng)開啟了它,就有兩個坑:

  • Linux 會加快客戶端和服務(wù)端 TIME_WAIT 狀態(tài)的時間,也就是它會使得 TIME_WAIT 狀態(tài)會小于 60 秒,很容易導(dǎo)致數(shù)據(jù)錯亂;
  • 另外,Linux 會丟棄所有來自遠端時間戳小于上次記錄的時間戳(由同一個遠端發(fā)送的)的任何數(shù)據(jù)包。就是說要使用該選項,則必須保證數(shù)據(jù)包的時間戳是單調(diào)遞增的。那么,問題在于,此處的時間戳并不是我們通常意義上面的絕對時間,而是一個相對時間。很多情況下,我們是沒法保證時間戳單調(diào)遞增的,比如使用了 NAT,LVS 等情況;

所以,不建議設(shè)置為 1 ,建議關(guān)閉它:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

在 Linux 4.12 版本后,Linux 內(nèi)核直接取消了這一參數(shù)。

另外,我們可以在程序中設(shè)置 socket 選項,來設(shè)置調(diào)用 close 關(guān)閉連接行為。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

如果l_onoff為非 0, 且l_linger值為 0,那么調(diào)用close后,會立該發(fā)送一個 RST 標志給對端,該 TCP 連接將跳過四次揮手,也就跳過了 TIME_WAIT 狀態(tài),直接關(guān)閉。

但這為跨越 TIME_WAIT 狀態(tài)提供了一個可能,不過是一個非常危險的行為,不值得提倡。

被動方的優(yōu)化

當(dāng)被動方收到 FIN 報文時,內(nèi)核會自動回復(fù) ACK,同時連接處于 CLOSE_WAIT 狀態(tài),顧名思義,它表示等待應(yīng)用進程調(diào)用 close 函數(shù)關(guān)閉連接。

內(nèi)核沒有權(quán)利替代進程去關(guān)閉連接,因為如果主動方是通過 shutdown 關(guān)閉連接,那么它就是想在半關(guān)閉連接上接收數(shù)據(jù)或發(fā)送數(shù)據(jù)。因此,Linux 并沒有限制 CLOSE_WAIT 狀態(tài)的持續(xù)時間。

當(dāng)然,大多數(shù)應(yīng)用程序并不使用 shutdown 函數(shù)關(guān)閉連接。所以,當(dāng)你用 netstat 命令發(fā)現(xiàn)大量 CLOSE_WAIT 狀態(tài)。就需要排查你的應(yīng)用程序,因為可能因為應(yīng)用程序出現(xiàn)了 Bug,read 函數(shù)返回 0 時,沒有調(diào)用 close 函數(shù)。

處于 CLOSE_WAIT 狀態(tài)時,調(diào)用了 close 函數(shù),內(nèi)核就會發(fā)出 FIN 報文關(guān)閉發(fā)送通道,同時連接進入 LAST_ACK 狀態(tài),等待主動方返回 ACK 來確認連接關(guān)閉。

如果遲遲收不到這個 ACK,內(nèi)核就會重發(fā) FIN 報文,重發(fā)次數(shù)仍然由 tcp_orphan_retries 參數(shù)控制,這與主動方重發(fā) FIN 報文的優(yōu)化策略一致。

還有一點我們需要注意的,如果被動方迅速調(diào)用 close 函數(shù),那么被動方的 ACK 和 FIN 有可能在一個報文中發(fā)送,這樣看起來,四次揮手會變成三次揮手,這只是一種特殊情況,不用在意。

如果連接雙方同時關(guān)閉連接,會怎么樣?

由于 TCP 是雙全工的協(xié)議,所以是會出現(xiàn)兩方同時關(guān)閉連接的現(xiàn)象,也就是同時發(fā)送了 FIN 報文。

此時,上面介紹的優(yōu)化策略仍然適用。兩方發(fā)送 FIN 報文時,都認為自己是主動方,所以都進入了 FIN_WAIT1 狀態(tài),F(xiàn)IN 報文的重發(fā)次數(shù)仍由 tcp_orphan_retries 參數(shù)控制。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

接下來,雙方在等待 ACK 報文的過程中,都等來了 FIN 報文。這是一種新情況,所以連接會進入一種叫做 CLOSING 的新狀態(tài),它替代了 FIN_WAIT2 狀態(tài)。接著,雙方內(nèi)核回復(fù) ACK 確認對方發(fā)送通道的關(guān)閉后,進入 TIME_WAIT 狀態(tài),等待 2MSL 的時間后,連接自動關(guān)閉。

小結(jié)

針對 TCP 四次揮手的優(yōu)化,我們需要根據(jù)主動方和被動方四次揮手狀態(tài)變化來調(diào)整系統(tǒng) TCP 內(nèi)核參數(shù)。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

主動方的優(yōu)化

主動發(fā)起 FIN 報文斷開連接的一方,如果遲遲沒收到對方的 ACK 回復(fù),則會重傳 FIN 報文,重傳的次數(shù)由?tcp_orphan_retries?參數(shù)決定。

當(dāng)主動方收到 ACK 報文后,連接就進入 FIN_WAIT2 狀態(tài),根據(jù)關(guān)閉的方式不同,優(yōu)化的方式也不同:

  • 如果這是 close 函數(shù)關(guān)閉的連接,那么它就是孤兒連接。如果?tcp_fin_timeout?秒內(nèi)沒有收到對方的 FIN 報文,連接就直接關(guān)閉。同時,為了應(yīng)對孤兒連接占用太多的資源,tcp_max_orphans?定義了最大孤兒連接的數(shù)量,超過時連接就會直接釋放。
  • 反之是 shutdown 函數(shù)關(guān)閉的連接,則不受此參數(shù)限制;

當(dāng)主動方接收到 FIN 報文,并返回 ACK 后,主動方的連接進入 TIME_WAIT 狀態(tài)。這一狀態(tài)會持續(xù) 1 分鐘,為了防止 TIME_WAIT 狀態(tài)占用太多的資源,tcp_max_tw_buckets?定義了最大數(shù)量,超過時連接也會直接釋放。

當(dāng) TIME_WAIT 狀態(tài)過多時,還可以通過設(shè)置?tcp_tw_reuse?和?tcp_timestamps?為 1 ,將 TIME_WAIT 狀態(tài)的端口復(fù)用于作為客戶端的新連接,注意該參數(shù)只適用于客戶端。

被動方的優(yōu)化

被動關(guān)閉的連接方應(yīng)對非常簡單,它在回復(fù) ACK 后就進入了 CLOSE_WAIT 狀態(tài),等待進程調(diào)用 close 函數(shù)關(guān)閉連接。因此,出現(xiàn)大量 CLOSE_WAIT 狀態(tài)的連接時,應(yīng)當(dāng)從應(yīng)用程序中找問題。

當(dāng)被動方發(fā)送 FIN 報文后,連接就進入 LAST_ACK 狀態(tài),在未等到 ACK 時,會在?tcp_orphan_retries參數(shù)的控制下重發(fā) FIN 報文。


03 TCP 傳輸數(shù)據(jù)的性能提升

在前面介紹的是三次握手和四次揮手的優(yōu)化策略,接下來主要介紹的是 TCP 傳輸數(shù)據(jù)時的優(yōu)化策略。

TCP 連接是由內(nèi)核維護的,內(nèi)核會為每個連接建立內(nèi)存緩沖區(qū):

  • 如果連接的內(nèi)存配置過小,就無法充分使用網(wǎng)絡(luò)帶寬,TCP 傳輸效率就會降低;
  • 如果連接的內(nèi)存配置過大,很容易把服務(wù)器資源耗盡,這樣就會導(dǎo)致新連接無法建立;

因此,我們必須理解 Linux 下 TCP 內(nèi)存的用途,才能正確地配置內(nèi)存大小。

滑動窗口是如何影響傳輸速度的?

TCP 會保證每一個報文都能夠抵達對方,它的機制是這樣:報文發(fā)出去后,必須接收到對方返回的確認報文 ACK,如果遲遲未收到,就會超時重發(fā)該報文,直到收到對方的 ACK 為止。

所以,TCP 報文發(fā)出去后,并不會立馬從內(nèi)存中刪除,因為重傳時還需要用到它。

由于 TCP 是內(nèi)核維護的,所以報文存放在內(nèi)核緩沖區(qū)。如果連接非常多,我們可以通過 free 命令觀察到?buff/cache?內(nèi)存是會增大。

如果 TCP 是每發(fā)送一個數(shù)據(jù),都要進行一次確認應(yīng)答。當(dāng)上一個數(shù)據(jù)包收到了應(yīng)答了, 再發(fā)送下一個。這個模式就有點像我和你面對面聊天,你一句我一句,但這種方式的缺點是效率比較低的。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

所以,這樣的傳輸方式有一個缺點:數(shù)據(jù)包的往返時間越長,通信的效率就越低。

要解決這一問題不難,并行批量發(fā)送報文,再批量確認報文即刻。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

然而,這引出了另一個問題,發(fā)送方可以隨心所欲的發(fā)送報文嗎?當(dāng)然這不現(xiàn)實,我們還得考慮接收方的處理能力。

當(dāng)接收方硬件不如發(fā)送方,或者系統(tǒng)繁忙、資源緊張時,是無法瞬間處理這么多報文的。于是,這些報文只能被丟掉,使得網(wǎng)絡(luò)效率非常低。

為了解決這種現(xiàn)象發(fā)生,TCP 提供一種機制可以讓「發(fā)送方」根據(jù)「接收方」的實際接收能力控制發(fā)送的數(shù)據(jù)量,這就是滑動窗口的由來。

接收方根據(jù)它的緩沖區(qū),可以計算出后續(xù)能夠接收多少字節(jié)的報文,這個數(shù)字叫做接收窗口。當(dāng)內(nèi)核接收到報文時,必須用緩沖區(qū)存放它們,這樣剩余緩沖區(qū)空間變小,接收窗口也就變小了;當(dāng)進程調(diào)用 read 函數(shù)后,數(shù)據(jù)被讀入了用戶空間,內(nèi)核緩沖區(qū)就被清空,這意味著主機可以接收更多的報文,接收窗口就會變大。

因此,接收窗口并不是恒定不變的,接收方會把當(dāng)前可接收的大小放在 TCP 報文頭部中的窗口字段,這樣就可以起到窗口大小通知的作用。

發(fā)送方的窗口等價于接收方的窗口嗎?如果不考慮擁塞控制,發(fā)送方的窗口大小「約等于」接收方的窗口大小,因為窗口通知報文在網(wǎng)絡(luò)傳輸是存在時延的,所以是約等于的關(guān)系。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

從上圖中可以看到,窗口字段只有 2 個字節(jié),因此它最多能表達 65535 字節(jié)大小的窗口,也就是 64KB 大小。

這個窗口大小最大值,在當(dāng)今高速網(wǎng)絡(luò)下,很明顯是不夠用的。所以后續(xù)有了擴充窗口的方法:在 TCP 選項字段定義了窗口擴大因子,用于擴大TCP通告窗口,使 TCP 的窗口定義從 2 個字節(jié)(16 位) 增加為 4 字節(jié)(32 位),所以此時窗口的最大值可以達到 1GB。

Linux 中打開這一功能,需要把 tcp_window_scaling 配置設(shè)為 1(默認打開):

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

要使用窗口擴大選項,通訊雙方必須在各自的 SYN 報文中發(fā)送這個選項:

  • 主動建立連接的一方在 SYN 報文中發(fā)送這個選項;
  • 而被動建立連接的一方只有在收到帶窗口擴大選項的 SYN 報文之后才能發(fā)送這個選項。

這樣看來,只要進程能及時地調(diào)用 read 函數(shù)讀取數(shù)據(jù),并且接收緩沖區(qū)配置得足夠大,那么接收窗口就可以無限地放大,發(fā)送方也就無限地提升發(fā)送速度。

這是不可能的,因為網(wǎng)絡(luò)的傳輸能力是有限的,當(dāng)發(fā)送方依據(jù)發(fā)送窗口,發(fā)送超過網(wǎng)絡(luò)處理能力的報文時,路由器會直接丟棄這些報文。因此,緩沖區(qū)的內(nèi)存并不是越大越好。

如果確定最大傳輸速度?

在前面我們知道了 TCP 的傳輸速度,受制于發(fā)送窗口與接收窗口,以及網(wǎng)絡(luò)設(shè)備傳輸能力。其中,窗口大小由內(nèi)核緩沖區(qū)大小決定。如果緩沖區(qū)與網(wǎng)絡(luò)傳輸能力匹配,那么緩沖區(qū)的利用率就達到了最大化。

問題來了,如何計算網(wǎng)絡(luò)的傳輸能力呢?

相信大家都知道網(wǎng)絡(luò)是有「帶寬」限制的,帶寬描述的是網(wǎng)絡(luò)傳輸能力,它與內(nèi)核緩沖區(qū)的計量單位不同:

  • 帶寬是單位時間內(nèi)的流量,表達是「速度」,比如常見的帶寬 100 MB/s;
  • 緩沖區(qū)單位是字節(jié),當(dāng)網(wǎng)絡(luò)速度乘以時間才能得到字節(jié)數(shù);

這里需要說一個概念,就是帶寬時延積,它決定網(wǎng)絡(luò)中飛行報文的大小,它的計算方式:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

比如最大帶寬是 100 MB/s,網(wǎng)絡(luò)時延(RTT)是 10ms 時,意味著客戶端到服務(wù)端的網(wǎng)絡(luò)一共可以存放 100MB/s * 0.01s = 1MB 的字節(jié)。

這個 1MB 是帶寬和時延的乘積,所以它就叫「帶寬時延積」(縮寫為 BDP,Bandwidth Delay Product)。同時,這 1MB 也表示「飛行中」的 TCP 報文大小,它們就在網(wǎng)絡(luò)線路、路由器等網(wǎng)絡(luò)設(shè)備上。如果飛行報文超過了 1 MB,就會導(dǎo)致網(wǎng)絡(luò)過載,容易丟包。

由于發(fā)送緩沖區(qū)大小決定了發(fā)送窗口的上限,而發(fā)送窗口又決定了「已發(fā)送未確認」的飛行報文的上限。因此,發(fā)送緩沖區(qū)不能超過「帶寬時延積」。

發(fā)送緩沖區(qū)與帶寬時延積的關(guān)系:

  • 如果發(fā)送緩沖區(qū)「超過」帶寬時延積,超出的部分就沒辦法有效的網(wǎng)絡(luò)傳輸,同時導(dǎo)致網(wǎng)絡(luò)過載,容易丟包;
  • 如果發(fā)送緩沖區(qū)「小于」帶寬時延積,就不能很好的發(fā)揮出網(wǎng)絡(luò)的傳輸效率。

所以,發(fā)送緩沖區(qū)的大小最好是往帶寬時延積靠近。

怎樣調(diào)整緩沖區(qū)大???

在 Linux 中發(fā)送緩沖區(qū)和接收緩沖都是可以用參數(shù)調(diào)節(jié)的。設(shè)置完后,Linux 會根據(jù)你設(shè)置的緩沖區(qū)進行動態(tài)調(diào)節(jié)。

調(diào)節(jié)發(fā)送緩沖區(qū)范圍

先來看看發(fā)送緩沖區(qū),它的范圍通過 tcp_wmem 參數(shù)配置;

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

上面三個數(shù)字單位都是字節(jié),它們分別表示:

  • 第一個數(shù)值是動態(tài)范圍的最小值,4096 byte = 4K;
  • 第二個數(shù)值是初始默認值,87380 byte ≈ 86K;
  • 第三個數(shù)值是動態(tài)范圍的最大值,4194304 byte = 4096K(4M);

發(fā)送緩沖區(qū)是自行調(diào)節(jié)的,當(dāng)發(fā)送方發(fā)送的數(shù)據(jù)被確認后,并且沒有新的數(shù)據(jù)要發(fā)送,就會把發(fā)送緩沖區(qū)的內(nèi)存釋放掉。

調(diào)節(jié)接收緩沖區(qū)范圍

而接收緩沖區(qū)的調(diào)整就比較復(fù)雜一些,先來看看設(shè)置接收緩沖區(qū)范圍的 tcp_rmem 參數(shù):

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

上面三個數(shù)字單位都是字節(jié),它們分別表示:

  • 第一個數(shù)值是動態(tài)范圍的最小值,表示即使在內(nèi)存壓力下也可以保證的最小接收緩沖區(qū)大小,4096 byte = 4K;
  • 第二個數(shù)值是初始默認值,87380 byte ≈ 86K;
  • 第三個數(shù)值是動態(tài)范圍的最大值,6291456 byte = 6144K(6M);

接收緩沖區(qū)可以根據(jù)系統(tǒng)空閑內(nèi)存的大小來調(diào)節(jié)接收窗口:

  • 如果系統(tǒng)的空閑內(nèi)存很多,就可以自動把緩沖區(qū)增大一些,這樣傳給對方的接收窗口也會變大,因而提升發(fā)送方發(fā)送的傳輸數(shù)據(jù)數(shù)量;
  • 反正,如果系統(tǒng)的內(nèi)存很緊張,就會減少緩沖區(qū),這雖然會降低傳輸效率,可以保證更多的并發(fā)連接正常工作;

發(fā)送緩沖區(qū)的調(diào)節(jié)功能是自動開啟的,而接收緩沖區(qū)則需要配置 tcp_moderate_rcvbuf 為 1 來開啟調(diào)節(jié)功能:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

調(diào)節(jié) TCP 內(nèi)存范圍

接收緩沖區(qū)調(diào)節(jié)時,怎么知道當(dāng)前內(nèi)存是否緊張或充分呢?這是通過 tcp_mem 配置完成的:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

上面三個數(shù)字單位不是字節(jié),而是「頁面大小」,1 頁表示 4KB,它們分別表示:

  • 當(dāng) TCP 內(nèi)存小于第 1 個值時,不需要進行自動調(diào)節(jié);
  • 在第 1 和第 2 個值之間時,內(nèi)核開始調(diào)節(jié)接收緩沖區(qū)的大?。?/li>
  • 大于第 3 個值時,內(nèi)核不再為 TCP 分配新內(nèi)存,此時新連接是無法建立的;

一般情況下這些值是在系統(tǒng)啟動時根據(jù)系統(tǒng)內(nèi)存數(shù)量計算得到的。根據(jù)當(dāng)前 tcp_mem 最大內(nèi)存頁面數(shù)是 177120,當(dāng)內(nèi)存為 (177120 * 4) / 1024K ≈ 692M 時,系統(tǒng)將無法為新的 TCP 連接分配內(nèi)存,即 TCP 連接將被拒絕。

根據(jù)實際場景調(diào)節(jié)的策略

在高并發(fā)服務(wù)器中,為了兼顧網(wǎng)速與大量的并發(fā)連接,我們應(yīng)當(dāng)保證緩沖區(qū)的動態(tài)調(diào)整的最大值達到帶寬時延積,而最小值保持默認的 4K 不變即可。而對于內(nèi)存緊張的服務(wù)而言,調(diào)低默認值是提高并發(fā)的有效手段。

同時,如果這是網(wǎng)絡(luò) IO 型服務(wù)器,那么,調(diào)大 tcp_mem 的上限可以讓 TCP 連接使用更多的系統(tǒng)內(nèi)存,這有利于提升并發(fā)能力。需要注意的是,tcp_wmem 和 tcp_rmem 的單位是字節(jié),而 tcp_mem 的單位是頁面大小。而且,千萬不要在 socket 上直接設(shè)置 SO_SNDBUF 或者 SO_RCVBUF,這樣會關(guān)閉緩沖區(qū)的動態(tài)調(diào)整功能。

小結(jié)

本節(jié)針對 TCP 優(yōu)化數(shù)據(jù)傳輸?shù)姆绞?,做了一些介紹。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

TCP 可靠性是通過 ACK 確認報文實現(xiàn)的,又依賴滑動窗口提升了發(fā)送速度也兼顧了接收方的處理能力。

可是,默認的滑動窗口最大值只有 64 KB,不滿足當(dāng)今的高速網(wǎng)絡(luò)的要求,要想要想提升發(fā)送速度必須提升滑動窗口的上限,在 Linux 下是通過設(shè)置?tcp_window_scaling?為 1 做到的,此時最大值可高達 1GB。

滑動窗口定義了網(wǎng)絡(luò)中飛行報文的最大字節(jié)數(shù),當(dāng)它超過帶寬時延積時,網(wǎng)絡(luò)過載,就會發(fā)生丟包。而當(dāng)它小于帶寬時延積時,就無法充分利用網(wǎng)絡(luò)帶寬。因此,滑動窗口的設(shè)置,必須參考帶寬時延積。

內(nèi)核緩沖區(qū)決定了滑動窗口的上限,緩沖區(qū)可分為:發(fā)送緩沖區(qū) tcp_wmem 和接收緩沖區(qū) tcp_rmem。

Linux 會對緩沖區(qū)動態(tài)調(diào)節(jié),我們應(yīng)該把緩沖區(qū)的上限設(shè)置為帶寬時延積。發(fā)送緩沖區(qū)的調(diào)節(jié)功能是自動打開的,而接收緩沖區(qū)需要把 tcp_moderate_rcvbuf 設(shè)置為 1 來開啟。其中,調(diào)節(jié)的依據(jù)是 TCP 內(nèi)存范圍 tcp_mem。

但需要注意的是,如果程序中的 socket 設(shè)置 SO_SNDBUF 和 SO_RCVBUF,則會關(guān)閉緩沖區(qū)的動態(tài)整功能,所以不建議在程序設(shè)置它倆,而是交給內(nèi)核自動調(diào)整比較好。

有效配置這些參數(shù)后,既能夠最大程度地保持并發(fā)性,也能讓資源充裕時連接傳輸速度達到最大值。

TCP 性能優(yōu)化詳解

https://www.zhuxiaodong.net/2018/tcp-performance-optimize-instruction/

延遲( latency )

延遲是指分組從信息源發(fā)送到目的地所需要的時間。影響延遲的因素包括:

  • 傳播延遲:消息從發(fā)送端到接收端需要的時間,是信號的傳播距離和速度的函數(shù)
  • 傳輸延遲:把消息中的所有比特轉(zhuǎn)移到鏈路中需要的時間,是消息長度和鏈路速率的函數(shù)
  • 處理延遲:處理分組首部、檢查位錯誤及確定分組目標所需的時間
  • 排隊延遲:到來的分組排隊等待處理的時間
    以上延遲的時間總和,就是客戶端到服務(wù)器的總延遲時間。

我們都知道,光在真空當(dāng)中的傳播速度大概是30萬公里/每秒,但是這是最理想的情況下網(wǎng)絡(luò)中傳播速度的極限值。實際上,根據(jù)不同的傳播介質(zhì),會影響到實際的傳輸速度。常見的介質(zhì)有銅絞線,光纖等。折射率是光速與分組在介質(zhì)中傳播速度之比,折射率越大,光在介質(zhì)中的傳播速度就越慢。基本上,以目前的技術(shù),傳播分組的光纖的大多數(shù)折射率在 1.4 ~ 1.6 之間。

我們假定光通過光纖的速度約20萬公里/每秒,對應(yīng)的折射率約為1.5,讓我們來看幾個實際例子:

路線 距離(km) 時間:光在真空中 時間:光在光纖中 光纖中的 RTT
紐約到舊金山 4148 14 ms 21 ms 42 ms
紐約到倫敦 5585 19 ms 28 ms 56 ms
紐約到悉尼 15993 53 ms 80 ms 160 ms
赤道周長 40075 133.7 ms 200 ms 400 ms

這里推薦一個根據(jù)目的地IP或者域名測試 RTT 的網(wǎng)站:http://tools.cloudxns.net/Index/Ping

此外,我們可以使用 traceroute ( windows 下是 tracert ) 命令,追蹤數(shù)據(jù)包在網(wǎng)絡(luò)上的傳輸時的全部路徑。traceroute 通過發(fā)送小的數(shù)據(jù)包到目的設(shè)備直到其返回,來測量其需要多長時間。一條路徑上的每個設(shè)備 traceroute 要測3次。輸出結(jié)果中包括每次測試的時間(ms)和設(shè)備的名稱(如有的話)及其ip地址。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

traceroute?www.newegg.com

traceroute?to?e5638.g.akamaiedge.net (23.35.193.40), 64?hops?max, 52?byte?packets

1 119.6.99.1 (119.6.99.1) 1.736?ms 5.620?ms 1.615?ms

2 119.6.193.73 (119.6.193.73) 2.442?ms 2.215?ms 2.322?ms

3 119.6.193.73 (119.6.193.73) 1.630?ms 2.225?ms 2.278?ms

4 119.6.195.13 (119.6.195.13) 42.078?ms

119.6.197.61 (119.6.197.61) 40.759?ms

119.6.197.57 (119.6.197.57) 38.476?ms

5 219.158.103.141 (219.158.103.141) 40.583?ms 38.999?ms 40.098?ms

6 * 219.158.4.170 (219.158.4.170) 43.155?ms 39.602?ms

7 219.158.3.50 (219.158.3.50) 39.884?ms 39.322?ms 39.744?ms

8?xe-4-1-0.r26.tokyjp05.jp.bb.gin.ntt.net (129.250.8.93) 82.547?ms 92.972?ms 82.852?ms

9?ae-1.r31.tokyjp05.jp.bb.gin.ntt.net (129.250.2.153) 114.856?ms

ae-0.r30.tokyjp05.jp.bb.gin.ntt.net (129.250.2.11) 123.523?ms 82.659?ms

10?ae-2.r03.tokyjp05.jp.bb.gin.ntt.net (129.250.3.33) 78.776?ms 78.786?ms

ae-3.r03.tokyjp05.jp.bb.gin.ntt.net (129.250.3.56) 111.784?ms

11 61.213.179.10 (61.213.179.10) 123.748?ms 127.927?ms 125.158?ms

12?a23-35-193-40.deploy.static.akamaitechnologies.com (23.35.193.40) 78.159?ms 77.882?ms 78.121?ms

關(guān)于 traceroute 更多內(nèi)容可以參考:?traceroute(8) - Linux man page

在 Mac 下,我們可以使用一個用戶體驗更好的工具,?BestTrace,能夠以地圖的方式顯示出每一跳的信息,非常直觀。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

如果不想安裝該軟件,也可以使用:TraceRoute查詢_專業(yè)精準的IP庫服務(wù)商_IPIP

帶寬 ( Bandwidth )

帶寬是指數(shù)據(jù)的發(fā)送速度。比如我們的百兆網(wǎng)卡,就是指網(wǎng)卡的最大發(fā)送速度為100Mbps(注意 b 是指 bit 而不是 byte)。發(fā)送速度和下面幾個因素有關(guān)系:

  • 數(shù)據(jù)發(fā)送裝置將二進制信號傳送至線路的能力,也稱之為信號傳輸頻率,以及另一端的數(shù)據(jù)接收裝置對二進制信號的接收能力,同時也包括線路對傳輸頻率的支持程度。

  • 數(shù)據(jù)傳播介質(zhì)的并行度,也可以稱之為寬度,完全等價于計算機系統(tǒng)總線寬度的概念。比如在光纖傳輸中,我們可以將若干條纖細的光纖并行組成光纜,這樣就可以在一個橫截面上同時傳輸多個信號,就像在32位的計算機總線中,可以同一時刻傳輸32位數(shù)據(jù)。需要注意的是,要提高計算機總線的帶寬,包括提高總線頻率和總線寬度兩種方法,比如使用64位總線系統(tǒng)或者使用主頻更高的處理器等。這兩種方法與以上數(shù)字通信帶寬的兩個決定因素完全相似。

如何實際的測試你的網(wǎng)絡(luò)帶寬?

雖然 ISP 或者 IDC 運營商有在你購買帶寬的時候,表明提供的帶寬大小,比如 100Mbps,但是那是理論值,很有可能實際的帶寬達不到官方宣傳的指標。

一般個人使用的 PC 上,可以使用?speedtest?來進行測試。 speedtest 能夠幫助你測試上傳速度和下載速度。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

另外國內(nèi)有一個類似的網(wǎng)站叫: www.speedtest.cn ,但是相對于 speedtest.net 來說,缺少切換服務(wù)器進行測試的功能。

如果你是在服務(wù)器上或者命令行想進行測試,可以選擇?speedtest-cli?進行測試

1

2

3

4

5

6

7

8

9

10

11

./speedtest-cli

Retrieving speedtest.net configuration...

Testing?from xx.xx.xx.xx. (xx.xx.xx.xx)...

Retrieving speedtest.net server list...

Selecting best server based on ping...

Hosted by xx.xx.xx.xx [4.87 km]:?31.317 ms

Testing download speed................................................................................

Download:?179.52 Mbit/s

Testing upload speed................................................................................................

Upload:?1.18 Mbit/s

You have new mail?in /var/spool/mail/root

可以看到,上述的測試結(jié)果還是比較準確的,Upload 顯示的為:1.18 Mbit/s ,而測試的這臺服務(wù)器的出口帶寬為 1 Mbit/s 。

關(guān)于帶寬的更多知識,強烈建議仔細閱讀《構(gòu)建高性能Web站點》?第二章

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

總結(jié)

可以通過上述的概念的描述,我們可以發(fā)現(xiàn), Latency 和 Bandwidth 決定了網(wǎng)絡(luò)性能,但是在絕大部分場景下,影響傳輸性能的最關(guān)鍵的因素是 Latency 。因為就算帶寬再高,我們也無法繞過由于物理距離帶來的高延遲問題。因此,減少延遲就作為了一個非常核心的優(yōu)化指標。

TCP Fast Open


設(shè)計目標

http 的 keepalive 受限于 idle 時間,據(jù) google 的統(tǒng)計( chrome 瀏覽器),盡管 chrome 開啟了 http 的 keepalive ( chrome 默認是4分鐘 ),可是依然有 35% 的請求是重新發(fā)起一條連接。而三次握手會造成一個 RTT 的延遲,因此 TFO 的目標就是去除這個延遲,在三次握手期間也能交換數(shù)據(jù)。

定義

TCP 快速打開是對 TCP 連接的一種簡化握手手續(xù)的拓展,用于提高兩端點間連接的打開速度。它通過握手開始時的 SYN 包中的 TFO cookie (一個TCP擴展選項)來驗證一個之前連接過的客戶端。如果驗證成功,它可以在三次握手最終的 ACK 包收到之前就開始發(fā)送數(shù)據(jù),這樣能夠減少一個 RTT 的時間,從而降低了延遲。這個加密的Cookie被存儲在客戶端,在一開始的連接時被設(shè)定好。然后每當(dāng)客戶端連接時,這個Cookie被重復(fù)返回。

具體的步驟參考下圖:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

開啟 nginx tcp fast open

在 Nginx 1.5.8 版本以及之后,listen 指令開始支持 fastopen 參數(shù)。需要注意的是:Linux 內(nèi)核版本必須在 3.7.1 以及以上的版本才支持 TCP fast open 。

首先需要內(nèi)核開啟對 tcp fast open 的支持:

1

2

3

4

sysctl -w net.ipv4.tcp_fastopen=3

# 或者要再重啟了之后永久生效,可以使用如下方式

echo?"net.ipv4.tcp_fastopen=3"?>> /etc/sysctl.conf

然后編譯 nginx 的時候需要增加參數(shù):

1

--with-cc-opt='-DTCP_FASTOPEN=23'

最后,修改 nginx 配置文件:

1

listen?80 fastopen=256

驗證請求是否有使用到 TCP Fast Open 有兩種方式:

  • 在服務(wù)器端直接觀察 TCP Fast Open 的狀態(tài),查看 TCPFastOpenPassive 字段的數(shù)字是否會隨著使用而增加。

1

2

3

grep?'^TcpExt:' /proc/net/netstat |?cut -d ' ' -f 91-96 |?column -t

TCPFastOpenPassive?TCPFastOpenPassiveFail?TCPFastOpenListenOverflow?TCPFastOpenCookieReqd?TCPSpuriousRtxHostQueues?BusyPollRxPackets

13 0 0 0 15 0

  • 使用 Wireshark 抓包:
    • 觀察客戶端出發(fā)的第一個 SYN 包,是否包含 TFO=R TCP 擴展選項
    • 觀察服務(wù)端回應(yīng)的 SYN-ACK 包,是否包含 TFO=C TCP 擴展選項
    • 觀察之后發(fā)出的 SYN 包,是否包含 TFO=C 標記,同時該包有 data
    • 若 1 失敗,說明客戶端沒有發(fā)出 TFO 請求
    • 若 2 失敗,說明服務(wù)器端配置有誤,未能正確啟動 TFO 支持

tcp fast open 目前的支持情況

目前大部分客戶端瀏覽器不支持,比如 chrome 只在 Linux,Android,Chrome OS 才支持,參考:這里;Microsoft Edge 從 Windows 10 Preview build 14352開始支持 TFO ;Mozilla Firefox 56 將支持 TFO 。

可見,在 web 瀏覽器端 TFO 并沒有得到普及。如果 google tcp fast open ,會發(fā)現(xiàn)其更多的應(yīng)用場景是用于優(yōu)化KeXueShagnWang的梯子上。例如,這里?和?這里

curl 客戶端支持 tfo ,可以使用下面的命令來開啟做測試:

1

curl --tcp-fastopen?https://www.zhuxiaodong.net

ref:

https://zh.wikipedia.org/wiki/TCP%E5%BF%AB%E9%80%9F%E6%89%93%E5%BC%80
Module ngx_http_core_module
Speed up web delivery with Nginx and TFO – UnixTeacher
https://gist.github.com/denji/8359866
RFC 7413 - TCP Fast Open
TFO(tcp fast open)簡介_51CTO博客_tcp fast open

基于 TCP 流量控制和擁塞控制的優(yōu)化


窗口縮放選項

我們在上一篇文章中已經(jīng)完整討論了 TCP 流量控制中:滑動窗口、默認的 rwnd (接收窗口)的大?。?2 ^ 16 = 65536 = 64KB )、窗口縮放選項及其對性能的影響等知識點,這里就不再累述。我們只需要注意,Linux 服務(wù)器的內(nèi)核版本選擇,需要高于 2.6.8 版本,這樣默認窗口擴大選項就是開啟的。

1

2

sysctl -n net.ipv4.tcp_window_scaling

1

初始擁塞窗口

還是在上一篇文章中,我們學(xué)習(xí)了擁塞控制相關(guān)的算法依賴于 TCP 連接初始化一個新的擁塞窗口( cwnd ),會將其設(shè)置成一個初始值,即: initcwnd 。cwnd 決定了發(fā)送端對接收端 ACK 之前,可以發(fā)送數(shù)據(jù)量的限制。

新 TCP 連接傳輸?shù)淖畲髷?shù)據(jù)量取 rwnd 和 cwnd 中的最小值。雖然服務(wù)器實際上可以向客戶端發(fā)送 4個 MSS ,但是最開始的時候必須停下來等待確認。此后,每收到一個 ACK ,慢啟動算法就會告訴服務(wù)器可以將它的 cwnd 窗口增加1個 MSS 。每次收到 ACK 后,都可以多發(fā)送兩個新的分組。TCP連接的這個階段通常被稱為“指數(shù)增長”階段,因為客戶端和服務(wù)器都在向兩者之間網(wǎng)絡(luò)路徑的有效帶寬迅速靠攏。上述算法決定了,無論你的帶寬有多大,都無法在一開始的時候就完全利用連接的最大帶寬。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

根據(jù)擁塞控制算法中的慢啟動算法,在分組被確認后逐步增加 cwnd 的大小。最初的時候,初始的 cwnd 的值只有 1 個 MSS ;1999年4月,RFC 2581 將其增加到了4個 MSS 。2013年4月,RFC 6928再次將其提高到10個 MSS 。

以下的公式描述了 cwnd 大小達到 N 字節(jié)大小所需要花費的時間:

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

我們來看實際的示例:

  • 客戶端和服務(wù)器的 rwnd 為 64 KB
  • initcwnd = 4 MSS ( RFC 2581 )
  • RTT = 56 ms

根據(jù)上面的公式,我們可以計算出:

  • 首先計算達到 N 字節(jié)的大?。ㄟ@里的 N = 64KB = 65535 byte),需要多少個 MSS,即: 65535 / 1460 = 45
  • 將 N 代入公式,可以計算出所需要花費的時間為 224 ms。

要達到客戶端與服務(wù)器之間64 KB的吞吐量,需要4次 RTT,幾百毫秒的延遲!至于客戶端與服務(wù)器之間實際的連接速率是不是在 Mbps 級別,絲毫不影響這個結(jié)果。這就是慢啟動。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

現(xiàn)在,假設(shè)只修改 initcwnd = 10 MSS ,其它條件都不變,根據(jù)上述公式,我們可以計算出其花費的時間只需要 168 ms。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

由此,我們得出結(jié)論,要想減少 TCP 連接中完全利用到最大帶寬的所花費的時間,要么減少 RTT (減少 RTT 其實就是減少物理距離),要么增加 initcwnd (盡量使用 Linux 內(nèi)核 2.6.39 之后的版本)。

關(guān)于 initcwnd 的更多信息,強烈建議閱讀一下 cdnplanet 的?這篇文章,文中完整的介紹了,初始窗口對傳輸時間的影響、擁塞控制的慢啟動算法、如何調(diào)整和查看 initcwnd 和 initrwnd 、調(diào)整了之后的測試結(jié)論等信息。以下的圖例是各個操作系統(tǒng),初始窗口的大小默認值(注意,是初始窗口大小,而不是初始擁塞窗口或者初始接收窗口的大小,rwin = min(initcwnd, initrwnd)?)

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

慢啟動重啟( Slow-Start Restart )

慢啟動重啟會在連接空閑一定時間后重置連接的擁塞窗口。道理很簡單,在連接空閑的同時,網(wǎng)絡(luò)狀況也可能發(fā)生了變化,為了避免擁塞,理應(yīng)將擁塞窗口重置回“安全的”默認值。

因此,慢啟動重啟對于那些會出現(xiàn)突發(fā)空閑的長周期TCP連接(比如 HTTP 的 keep-alive 連接)有很大的影響。因此,我們建議在服務(wù)器上禁用慢啟動重啟。在Linux平臺,可以通過如下命令來檢查和禁用慢啟動重啟:

1

2

3

4

5

6

sysctl -n net.ipv4.tcp_slow_start_after_idle

1

vim /etc/sysctl.conf

net.ipv4.tcp_slow_start_after_idle=0

sysctl -p

三次握手和慢啟動對 HTTP 傳輸性能的影響

為了更好的說明三次握手以及慢啟動階段對 HTTP 傳輸性能的影響,讓我們看一個實際的例子。我們假設(shè)涉及的相關(guān)參數(shù)信息如下:

  • http 請求文件的文件大?。?64 KB
  • RTT:56 ms
  • rwnd : 64 KB
  • bandwidth: 5 Mbps
  • initcwnd : 10 ( 10 x 1460 byte = 14 KB)
  • 服務(wù)器端處理請求所花費的時間: 40 ms
  • 傳輸過程中沒有發(fā)生丟包,每個數(shù)據(jù)包都要確認,GET 請求值只占 1 段。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

從上述的圖示中我們可以看出,傳輸 64 KB 的文件需要總共花費 264 ms 的時間。

我們假設(shè) TCP 連接能夠重用同一個連接,重復(fù)上述的過程重新進行傳輸,其過程大概如下:

  • 0 ms : 客戶端發(fā)起 http 請求
  • 28 ms : 服務(wù)器端接收到 http 請求
  • 68 ms : Server 端花費了 40 ms 的時間處理 64 KB 響應(yīng),此時的 cwnd 的大小已經(jīng)超過了 45 MSS 的大小,因此,直接將整個 64 KB 的文件直接一次性的進行發(fā)送。
  • 96 ms : 客戶端接收到了所有的 64 KB的文件。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

同樣的一次請求,相比了第一個示例中的 268 ms 處理時間,第二個示例僅僅花費了 96 ms ,性能提升了 275% 。原因在于第二個示例,沒有三次握手的 RTT 延遲,以及沒有初期慢啟動達到最佳狀態(tài)時,所帶來的時間消耗。

同時我們還可以看到,5 Mbps 的 bandwidth 實際上在 TCP 連接的初始階段,對性能沒有任何影響。主要影響因素還是 latency 和 cwnd 的大小。

采用更好的擁塞預(yù)防算法–PRR 算法

在上一篇文章中,我們也學(xué)習(xí)了擁塞預(yù)防的相關(guān)知識,這里就簡單的復(fù)習(xí)一下,加深一下印象。

慢啟動初始以 initcwnd 為大小成倍增加 cwnd 的值之后,當(dāng)超過了接收端流量控制的擁塞閾值,即 ssthresh 窗口,或者在傳輸過程有發(fā)生丟包,此時就會采用擁塞預(yù)防算法。擁塞預(yù)防算法把丟包作為網(wǎng)絡(luò)擁塞的標志,即路徑中某個連接或路由器已經(jīng)擁堵了,以至于必須采取刪包措施。因此,必須調(diào)整窗口大小,以避免造成更多的包丟失,從而保證網(wǎng)絡(luò)暢通。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

確定丟包恢復(fù)的最優(yōu)方式并不容易。如果太激進,那么間歇性的丟包就會對整個連接的吞吐量造成很大影響。而如果不夠快,那么還會繼續(xù)造成更多分組丟失。

最初,TCP 使用 AIMD( Multiplicative Decrease and Additive Increase ,倍減加增)算法,即發(fā)生丟包時,先將擁塞窗口減半,然后每次往返再緩慢地給窗口增加一個固定的值。不過,很多時候 AIMD 算法太過保守,因此又有了新的算法。

PRR(Proportional Rate Reduction,比例降速)就是RFC 6937規(guī)定的一個新算法,其目標就是改進丟包后的恢復(fù)速度。根據(jù)谷歌的測量,實現(xiàn)新算法后,因丟包造成的平均連接延遲減少了3%~10% 。

需要注意的是, PRR 算法從 Linux 3.2 版本才開始支持。

帶寬延遲積與窗口大小的關(guān)系

關(guān)于 BDP 的概念我們已經(jīng)在在上一篇文章中學(xué)習(xí)過了,現(xiàn)在我們知道了,發(fā)送端和接收端之間在途未確認的最大數(shù)據(jù)量,取決于擁塞窗口( cwnd )和接收窗口( rwnd )的最小值。接收窗口會隨每次 ACK 一起發(fā)送,而擁塞窗口則由發(fā)送端根據(jù)擁塞控制和預(yù)防算法動態(tài)調(diào)整。

無論發(fā)送端發(fā)送的數(shù)據(jù)還是接收端接收的數(shù)據(jù)超過了未確認的最大數(shù)據(jù)量,都必須停下來等待另一方 ACK 確認某些分組才能繼續(xù)。要等待多長時間呢?取決于往返時間!

BDP(Bandwidth-delay product,帶寬延遲積):數(shù)據(jù)鏈路的容量與其端到端延遲的乘積。這個結(jié)果就是任意時刻處于在途未確認狀態(tài)的最大數(shù)據(jù)量。

因此想要充分利用帶寬,必須讓窗口大小接近 BDP 的大小,才能確保最大吞吐量。

我們通過如下的例子來討論一下,究竟 rwnd 和 cwnd 的值與理論最大使用帶寬的關(guān)系是什么?

  • min(cwnd, rwnd) = 16 KB
  • RTT = 100 ms
  • 16 KB = 16 X 1024 X 8 = 131072 bits
  • 131072 / 0.1 = 1310720 bits/s
  • 1310720 bits/s = 1310720 / 1000000 = 1.31 Mbps

因此,無論發(fā)送端和接收端的實際帶寬為多大,當(dāng)窗口大小為 16 KB 時,傳輸速率最大只能為 1.31 Mbps 。

再來看另外一個例子,假設(shè)發(fā)送端的帶寬為 10 Mbps ,接收端的帶寬為 100 Mbps,RTT 為 100 ms。如果我們想要充分利用帶寬,也就是客戶端的 10 Mbps,那么計算出的最小窗口值為:

  • 10 Mbit/s = 10 X 1000000 = 10000000 bit/s
  • 10000000 bit/s = 10000000 / (8 X 1024) = 1221 KB/s
  • 1221 KB/s X 0.1 s = 122.1 KB

因此,我們至少需要 122.1 KB 的窗口大小才能充分利用 10 Mbps 的帶寬。并且,如果要想盡量達到最大吞吐量的帶寬速度,要么增加窗口大小,要么減少 RTT 。

隊首阻塞 ( Head-of-line Blocking )

所謂的隊首阻塞是指,由于 TCP 的可靠性和順序到達的特性,要求所有的數(shù)據(jù)包必須按順序傳送到接收端。如果中途有任意一個數(shù)據(jù)包沒能到達接收端,那么后續(xù)的數(shù)據(jù)包必須保存在接收端的 TCP 緩沖區(qū),等待丟失的數(shù)據(jù)包重發(fā)并到達接收端。由于應(yīng)用程序?qū)?TCP 重發(fā)和緩沖區(qū)中排隊的數(shù)據(jù)包一無所知,必須等待所有數(shù)據(jù)包全部到達了之后才能訪問數(shù)據(jù),因此,應(yīng)用程序只能在通過套接字數(shù)據(jù)時感覺到延遲交付。

Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀,linux,Linux,tcp,內(nèi)核,講解,參數(shù),調(diào)優(yōu)

隊首阻塞造成的延遲可以讓我們的應(yīng)用程序不用關(guān)心分組重排和重組,但是數(shù)據(jù)包到達時間會存在無法預(yù)知的延遲變化,這個時間變化通常被稱為抖動,也是影響應(yīng)用程序性能的一個主要因素。

結(jié)論:無需按序交付數(shù)據(jù)或能夠處理分組丟失的應(yīng)用程序,以及延遲或抖動要求很高應(yīng)用程序,可以考慮 UDP 協(xié)議。

總結(jié)


盡管 TCP 協(xié)議相關(guān)的優(yōu)化算法正在不斷地發(fā)展,但是其核心原理以及它們的影響是不變的:

  • TCP三次握手增加了整整一次往返時間
  • TCP慢啟動將被應(yīng)用到每個新連接
  • TCP流量及擁塞控制會影響所有連接的吞吐量
  • TCP的吞吐量由當(dāng)前擁塞窗口大小控制

在大多數(shù)情況下,TCP 性能的瓶頸都是延遲,而非帶寬。

Check List:

    • 把服務(wù)器內(nèi)核升級到最新版本(Linux:3.2+)
    • 確保 cwnd 大小為10 ( 通過 ip route show 進行查看 )
    • 禁用空閑后的慢啟動 ( tcp_slow_start_after_idle = 0 )
    • 確保啟動窗口縮放( net.ipv4.tcp_window_scaling = 1 )
    • 減少傳輸冗余數(shù)據(jù)
    • 壓縮要傳輸?shù)臄?shù)
    • 把服務(wù)器放到離用戶近的地方以減少 RTT
    • 盡最大可能重用已經(jīng)建立的TCP連接

TCP參數(shù)參數(shù)調(diào)優(yōu) - lsgxeva - 博客園
https://www.cnblogs.com/lsgxeva/p/16276794.html

TCP參數(shù)參數(shù)調(diào)優(yōu) - 知乎
https://zhuanlan.zhihu.com/p/622683704文章來源地址http://www.zghlxwxcb.cn/news/detail-516320.html

到了這里,關(guān)于Linux內(nèi)核TCP參數(shù)調(diào)優(yōu)全面解讀的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • linux內(nèi)核tcp配置--斷網(wǎng)后連接卡住

    目前odbc版本2.3.1,不支持設(shè)置連接屬性(連接超時、命令請求超時等),需要odbc版本3.0以上。可通過設(shè)置tcp內(nèi)核參數(shù)(重傳次數(shù))來縮短超時時間。 使用命令行可以方便地查看已安裝的 ODBC的版本信息。 打開終端。 輸入以下命令來查看MySQL ODBC的版本: 這將顯示已安裝的O

    2024年02月05日
    瀏覽(22)
  • Linux內(nèi)核源碼剖析之TCP?;顧C制(KeepAlive)

    版本信息: Linux內(nèi)核2.6.24(大部分centos、ubuntu應(yīng)該都在3.1+。但是2.6的版本比較穩(wěn)定,后續(xù)版本本質(zhì)變化也不是很大) ipv4 協(xié)議 https://blog.csdn.net/ComplexMaze/article/details/124201088 本文使用案例如上地址,感謝案例的分享,本篇文章核心部分還是在Linux內(nèi)核源碼分析~ 為什么寫下這

    2024年02月12日
    瀏覽(24)
  • Linux內(nèi)核中的TCP/IP協(xié)議棧源代碼分析

    Linux內(nèi)核中的TCP/IP協(xié)議棧源代碼分析

    目錄 背景知識-Linux源碼簡介 TCP/IP協(xié)議棧相關(guān)問題 inet_init是如何被調(diào)用的?從start_kernel到inet_init調(diào)用路徑 1.start_kernel(): 2.inet_init()?: 3.fs_initcall() 跟蹤分析TCP/IP協(xié)議棧如何將自己與上層套接口與下層數(shù)據(jù)鏈路層關(guān)聯(lián)起來的? TCP的三次握手源代碼跟蹤分析,跟蹤找出設(shè)置和發(fā)

    2024年02月02日
    瀏覽(48)
  • TCP緩沖區(qū)參數(shù)調(diào)優(yōu)

    1、系統(tǒng)原值查詢 2、設(shè)置值 3、參數(shù)解析 tcp_wmem(3個INTEGER變量):?min,?default,?max **min:**為TCP socket預(yù)留用于發(fā)送緩沖的內(nèi)存最小值。每個tcp socket都可以在建議以后都可以使用它。默認值為4096(4K)。 **default:**為TCP socket預(yù)留用于發(fā)送緩沖的內(nèi)存數(shù)量,默認情況下該值會影響其它

    2024年02月11日
    瀏覽(22)
  • linux服務(wù)TCP參數(shù)配置

    linux服務(wù)TCP參數(shù)配置

    阿里云規(guī)范 1.【推薦】高并發(fā)服務(wù)器建議調(diào)小 TCP 協(xié)議的 time_wait 超時時間。 說明:操作系統(tǒng)默認 240 秒后,才會關(guān)閉處于 time_wait 狀態(tài)的連接,在高并發(fā)訪問下,服務(wù)器端會因為處于 time_wait 的連接數(shù)太多,可能無法建立新的連接,所以需要在服務(wù)器上調(diào)小此等待值。 正例:

    2024年02月11日
    瀏覽(16)
  • 性能分析與調(diào)優(yōu): Linux 使用 iperf3 進行TCP網(wǎng)絡(luò)吞吐量測試

    性能分析與調(diào)優(yōu): Linux 使用 iperf3 進行TCP網(wǎng)絡(luò)吞吐量測試

    目錄 一、實驗 1.環(huán)境 2.TCP網(wǎng)絡(luò)吞吐量的微觀基準測試 二、問題 1.iperf參數(shù)有哪些 2.iperf如何二進制安裝 (1)主機 表1-1 主機 主機 架構(gòu) 組件 IP 備注 prometheus 監(jiān)測 系統(tǒng) prometheus、node_exporter ?192.168.204.18 grafana 監(jiān)測GUI grafana 192.168.204.19 agent? 監(jiān)測 主機 node_exporter 192.168.204.20 (1)

    2024年02月03日
    瀏覽(38)
  • Linux內(nèi)核--網(wǎng)絡(luò)協(xié)議棧(五)TCP IP棧的實現(xiàn)原理與具體過程

    一、引言 二、Linux內(nèi)核的結(jié)構(gòu) 三、Linux網(wǎng)絡(luò)子系統(tǒng) 四、TCP/IP協(xié)議棧 ------4.1、網(wǎng)絡(luò)架構(gòu) ------4.2、協(xié)議無關(guān)接口 ------4.3、套接口緩存 ------4.4、重要的數(shù)據(jù)結(jié)構(gòu) 五、網(wǎng)絡(luò)信息處理流程 ------5.1、硬中斷處理 ------5.2、ksoftirqd內(nèi)核線程處理軟中斷 ------5.3、網(wǎng)絡(luò)協(xié)議棧處理 ------5.4、

    2024年01月21日
    瀏覽(96)
  • Linux 服務(wù)器 TCP 連接數(shù)參數(shù)調(diào)整

    服務(wù)器?es 或增加 nginx 要想增加處理能力,調(diào)整 TCP 連接數(shù)可以通過修改操作系統(tǒng)的TCP參數(shù)來實現(xiàn),以下是具體操作步驟,在此做下記錄: 1、查看系統(tǒng)TCP連接資源命令 2、調(diào)整操作系統(tǒng)的最大連接數(shù)限制? ?????????/etc/sysctl.conf 文件 ????????然后運行以下命令使設(shè)置生

    2024年04月09日
    瀏覽(26)
  • 系統(tǒng)運維-Rocky Linux9.0配置IP地址TCP/IP參數(shù)

    在Rocky9中,丟棄使用了傳統(tǒng)的network 而使用新的NetworkManager管理方式 所有較之前的版本配置方式有所不同 先查看下未配置前現(xiàn)在的ip參數(shù) 可以看到現(xiàn)在是dhcp獲取的192.168.252.151 現(xiàn)在配置一下靜態(tài): 更改 [ipv4] 那段: 更改完成后保存退出 接下來寫入配置文件 再更新一下網(wǎng)卡配

    2024年02月11日
    瀏覽(43)
  • 性能分析與調(diào)優(yōu): Linux 使用ELRepo升級CentOS內(nèi)核

    性能分析與調(diào)優(yōu): Linux 使用ELRepo升級CentOS內(nèi)核

    目錄 一、實驗 1.環(huán)境 2.agent 服務(wù)器使用ELRepo升級CentOS內(nèi)核 二、問題 1.?RHEL-7, SL-7 或者 CentOS-7系統(tǒng)如何安裝ELRepo 2.RHEL-8或者RHEL-9系統(tǒng)如何安裝ELRepo (1)主機 表1-1 主機 主機 架構(gòu) 組件 IP 備注 prometheus 監(jiān)測 系統(tǒng) prometheus、node_exporter ?192.168.204.18 grafana 監(jiān)測GUI grafana 192.168.204.19

    2024年01月23日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包