如何提升 TCP 傳輸數據的性能?詳解

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

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

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

如果 TCP 是每發送一個數據,都要進行一次確認應答。當上一個數據包收到了應答了, 再發送下一個。這個模式就有點像我和你面對面聊天,你一句我一句,但這種方式的缺點是效率比較低的
在這里插入圖片描述
所以,這樣的傳輸方式有一個缺點:數據包的往返時間越長,通信的效率就越低

要解決這一問題不難,并行批量發送報文,再批量確認報文即可
在這里插入圖片描述
然而,這引出了另一個問題,發送方可以隨心所欲的發送報文嗎?當然這不現實,我們還得考慮接收方的處理能力

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

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

接收方根據它的緩沖區,可以計算出后續能夠接收多少字節的報文,這個數字叫做接收窗口。當內核接收到報文時,必須用緩沖區存放它們,這樣剩余緩沖區空間變小,接收窗口也就變小了;當進程調用read 函數后,數據被讀入了用戶空間,內核緩沖區就被清空,這意味著主機可以接收更多的報文,接收窗口就會變大

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

發送方的窗口等價于接收方的窗口嗎?如果不考慮擁塞控制,發送方的窗口大小「約等于」接收方的窗口大小,因為窗口通知報文在網絡傳輸是存在時延的,所以是約等于的關系
在這里插入圖片描述
從上圖中可以看到,窗口字段只有 2 個字節,因此它最多能表達65535 字節大小的窗口,也就是 64KB 大小

這個窗口大小最大值,在當今高速網絡下,很明顯是不夠用的。所以后續有了擴充窗口的方法:在 TCP 選項字段定義了窗口擴大因子,用于擴大 TCP 通告窗口,其值大小是 2^14,這樣就使 TCP 的窗口大小從16 位擴大為 30 位(2^16 * 2^ 14 = 2^30),所以此時窗口的最大值可以達到 1GB
在這里插入圖片描述
Linux 中打開這一功能,需要把 tcp_window_scaling 配置設為 1(默認打開):
在這里插入圖片描述
要使用窗口擴大選項,通訊雙方必須在各自的 SYN 報文中發送這個選項:

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

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

這是不可能的,因為網絡的傳輸能力是有限的,當發送方依據發送窗口,發送超過網絡處理能力的報文時,路由器會直接丟棄這些報文。因此,緩沖區的內存并不是越大越好

如何確定最大傳輸速度?

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

問題來了,如何計算網絡的傳輸能力呢?

相信大家都知道網絡是有「帶寬」限制的,帶寬描述的是網絡傳輸能力,它與內核緩沖區的計量單位不同:

  • 帶寬是單位時間內的流量,表達是「速度」,比如常見的帶寬 100 MB/s
  • 緩沖區單位是字節,當網絡速度乘以時間才能得到字節數

這里需要說一個概念,就是帶寬時延積,它決定網絡中飛行報文的大小,它的計算方式:
在這里插入圖片描述
比如最大帶寬是 100 MB/s,網絡時延(RTT)是 10ms 時,意味著客戶端到服務端的網絡一共可以存放 100MB/s * 0.01s = 1MB 的字節

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

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

發送緩沖區與帶寬時延積的關系:

  • 如果發送緩沖區「超過」帶寬時延積,超出的部分就沒辦法有效的網絡傳輸,同時導致網絡過載,容易丟包
  • 如果發送緩沖區「小于」帶寬時延積,就不能很好的發揮出網絡的傳輸效率

所以,發送緩沖區的大小最好是往帶寬時延積靠近

怎樣調整緩沖區大小?

在 Linux 中發送緩沖區和接收緩沖都是可以用參數調節的。設置完后,Linux 會根據你設置的緩沖區進行動態調節

1、調節發送緩沖區范圍

先來看看發送緩沖區,它的范圍通過 tcp_wmem 參數配置;
在這里插入圖片描述
上面三個數字單位都是字節,它們分別表示:

  • 第一個數值是動態范圍的最小值,4096 byte = 4K
  • 第二個數值是初始默認值,16384 byte ≈ 16K
  • 第三個數值是動態范圍的最大值,4194304 byte = 4096K(4M)

發送緩沖區是自行調節的,當發送方發送的數據被確認后,并且沒有新的數據要發送,就會把發送緩沖區的內存釋放掉

2、調節接收緩沖區范圍

而接收緩沖區的調整就比較復雜一些,先來看看設置接收緩沖區范圍的 tcp_rmem 參數:
在這里插入圖片描述
上面三個數字單位都是字節,它們分別表示:

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

接收緩沖區可以根據系統空閑內存的大小來調節接收窗口:

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

發送緩沖區的調節功能是自動開啟的,而接收緩沖區則需要配置
tcp_moderate_rcvbuf 為 1 來開啟調節功能:
在這里插入圖片描述

3、調節 TCP 內存范圍

接收緩沖區調節時,怎么知道當前內存是否緊張或充分呢?這是通過tcp_mem 配置完成的:
在這里插入圖片描述
上面三個數字單位不是字節,而是「頁面大小」,1 頁表示 4KB,它們分別表示:

  • 當 TCP 內存小于第 1 個值時,不需要進行自動調節
  • 在第 1 和第 2 個值之間時,內核開始調節接收緩沖區的大小
  • 大于第 3 個值時,內核不再為 TCP 分配新內存,此時新連接是無法建立的

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

4、根據實際場景調節的策略

在高并發服務器中,為了兼顧網速與大量的并發連接,我們應當保證緩沖區的動態調整的最大值達到帶寬時延積,而最小值保持默認的 4K不變即可。而對于內存緊張的服務而言,調低默認值是提高并發的有效手段

同時,如果這是網絡 IO 型服務器,那么,調大 tcp_mem 的上限可以讓 TCP 連接使用更多的系統內存,這有利于提升并發能力。需要注意的是,tcp_wmem 和 tcp_rmem 的單位是字節,而 tcp_mem 的單位是頁面大小。而且,千萬不要在 socket 上直接設置 SO_SNDBUF 或者SO_RCVBUF,這樣會關閉緩沖區的動態調整功能

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916902.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916902.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916902.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WiFi連接簡單流程

WiFi連接流程與Debug方法一、WiFi連接全流程與詳細日志解讀 WiFi連接是一個多階段、跨層次的復雜過程,涉及物理層、鏈路層、網絡層和應用層的多種協議協作。整個流程包括AP初始化、終端掃描、認證、關聯、四次握手、DHCP獲取IP、網絡可用與后續服務。1. AP初始化與參…

Python——Pandas庫,超詳細教程

前言1、Python的Pandas是一個基于Python構建的開源數據分析庫,它提供了強大的數據結構和運算功能。2、Series:一維數組,類似于Numpy中的一維array,但具有索引標簽,可以保存不同類型的數據,如字符串、布爾值…

go語言的gRPC教程-protobuf基礎

一、前言 RPC,全稱Remote Procedure Call,中文譯為遠程過程調用。通俗地講,使用RPC進行通信,調用遠程函數就像調用本地函數一樣,RPC底層會做好數據的序列化與傳輸,從而能使我們更輕松地創建分布式應用和服…

Linux基本指令,對路徑的認識

引言簡單介紹一些Linux的基本指令,快速上手Linux操作系統。一、ls指令語法:ls [選項] [目錄或文件]功能::對于目錄,該命令列出該目錄下的所有子目錄與文件。對于文件件,將列出文件名以及其他信息常用選項&a…

25. html 使用的字符集是什么,有什么特點

總結 utf-8&#xff0c;支持所有語言一、HTML 默認使用的字符集? HTML 頁面推薦使用 UTF-8 字符集<meta charset"UTF-8" />這是 HTML5 中推薦的標準字符編碼&#xff0c;用于定義網頁中字符的編碼方式。二、什么是字符集&#xff08;Character Encoding&#…

MySQL 讀寫分離(含示例代碼)

背景 面對日益增加的系統訪問量,數據庫的吞吐量面臨著巨大瓶頸。對于同一時刻有大量并發讀操作和較少寫操作類型的應用系統來說,將數據庫拆分為主庫和從庫,主庫負責處理事務性的增刪改操作,從庫負責處理查詢操作,能夠有效的避免由數據更新導致的行鎖,使得整個系統的查詢性…

C#中Visual Studio平臺按照OfficeOpenXml步驟

找到包的地址&#xff1a; NuGet Gallery | DocumentFormat.OpenXml.Framework 3.3.0 https://nuget.info/packages 報錯&#xff1a; 嚴重性 代碼 說明 項目 文件 行 禁止顯示狀態 錯誤 無法解析依賴項“EPPlus”。使用的源: Officeopenxml, Mic…

【Linux】重生之從零開始學習運維之備份恢復

備份恢復準備工作16主機-ubuntu系統準備日志目錄mkdir -p /data/mysql/logs/ chown mysql:mysql -R /data/mysql定制日志配置vim /etc/mysql/mariadb.conf.d/50-server.cnf log_bin/data/mysql/logs/binlog systemctl restart mariadb刪除db1數據庫drop database db1;13主機-ub…

VoIP技術全面深度學習指南:從原理到實踐的認知進化

一、VoIP技術的本質認知與歷史演進 1.1 技術本質的深層理解 VoIP&#xff08;Voice over Internet Protocol&#xff0c;IP語音傳輸&#xff09;從根本上代表了通信技術的范式轉換。這不僅僅是將模擬語音信號數字化那么簡單&#xff0c;而是將傳統的電路交換模式徹底轉向包交換…

CentOS Nginx 1.13.9 部署文檔

以下是 Nginx 1.13.9 的詳細安裝步驟&#xff08;基于 CentOS/Ubuntu 系統&#xff09;&#xff1a;1. 安裝依賴 CentOS/RHEL sudo yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-develUbuntu/Debian sudo apt update && sudo apt install -y b…

CSS-in-JS 動態主題切換與首屏渲染優化

動態主題切換的實現方式1. 使用 CSS 變量&#xff08;CSS Custom Properties&#xff09;CSS 變量是實現主題切換最直接的方式&#xff1a;:root {--primary-color: #4285f4;--background-color: #ffffff;--text-color: #333333; }[data-theme"dark"] {--primary-col…

不止 “聽懂”,更能 “感知”!移遠通信全新AI 音頻模組 重新定義智能家居“聽覺”邏輯

7月29日&#xff0c;在 2025 世界人工智能大會&#xff08;WAIC&#xff09;期間&#xff0c;移遠通信正式發布全新 VA500-GL AI 音頻模組。該產品基于本地化 AI 算法&#xff0c;為智能家電賦予精準 “聽覺” 與主動交互能力&#xff0c;借助環境狀態智能檢測、離線語音控制及…

【Python】 切割圖集的小腳本

Python 切割圖片腳本 前言&#xff1a; 有短時間沒寫博客了&#xff0c;今天打算再寫一篇MonoGame的教程&#xff0c;這篇是我再做我自己的2D 游戲項目的時候我需要一些已經切割好的圖片但我得到圖片是合在一起圖集&#xff0c;這個腳本適合正在做2D游戲開發且不依賴于游戲引…

網絡安全是什么?手把手教你認識網絡安全

網絡安全是什么&#xff1f;手把手教你認識網絡安全 提到網絡安全&#xff0c;不少人會聯想到電影里黑客指尖翻飛攻破系統的炫酷場景。但實際上&#xff0c;它并非遙不可及的技術名詞&#xff0c;而是與我們日常生活息息相關的 “數字保鏢”。從手機支付密碼到社交賬號信息&am…

AtCoder Beginner Contest 416(2025.7.26)

文章目錄A Vacation ValidationB 1D Akari&#xff08;補&#xff09;C Concat (X-th)&#xff08;補&#xff09;題目考查題意簡述解法思路 &#xff1a;AC代碼D Match, Mod, Minimize 2&#xff08;補&#xff09;題目分數/評級題目考查時間復雜度題意簡述解法思路 &#xff…

基于 Hadoop 生態圈的數據倉庫實踐 —— OLAP 與數據可視化(五)

目錄 五、Hue、Zeppelin 比較 1. Zeppelin 簡介 2. Zeppelin 安裝配置 &#xff08;1&#xff09;安裝環境 &#xff08;2&#xff09;Zeppelin 及其相關組件 &#xff08;3&#xff09;配置 Zeppelin &#xff08;4&#xff09;啟動 Zeppelin &#xff08;5&#xff0…

《消息隊列學習指南:從 MQ 基礎到 SpringAMQP 實踐》

初識MQ 同步調用 目前我們采用的是基于OpenFeign的同步調用&#xff0c;也就是說業務執行流程是這樣的&#xff1a; 支付服務需要先調用用戶服務完成余額扣減 然后支付服務自己要更新支付流水單的狀態 然后支付服務調用交易服務&#xff0c;更新業務訂單狀態為已支付 三個…

深度學習 --- 過擬合與欠擬合

深度學習 — 過擬合與欠擬合 文章目錄深度學習 --- 過擬合與欠擬合一.概念1.1 過擬合1.2 欠擬合1.3 判斷方式二&#xff0c;解決欠擬合三&#xff0c;解決過擬合3.1 L2正則化3.1.1 定義以及作用3.1.2 代碼3.2 L1正則化3.3 L1與L2對比3.4 Dropout示例3.5 數據增強3.5.1 圖片縮放…

Python 之抽象方法 @abstractmethod 的理解

如果你熟悉 Java 的話&#xff0c;Java 里有一個抽象接口的概念&#xff0c;Python 里的抽象方法基本上與其類似。在 Python 中&#xff0c;abstractmethod 是一個裝飾器&#xff0c;用于定義抽象方法。它是實現抽象基類&#xff08;Abstract Base Class, ABC&#xff09;的核心…

深度學習·pytorch

廣播機制 從末尾開始逐個維度遍歷兩個矩陣的shape&#xff0c;如果維度不相同&#xff0c;則考慮廣播&#xff1a;任一方的維度為1或者維度不存在(小矩陣廣播為大矩陣)&#xff0c;這樣的運算可以廣播 可以廣播的例子 xtorch.empty(5,3,4,1) ytorch.empty(3,1,1) (x.add_(y)).s…