本文分享自華為雲社群《【高并發】高并發場景下如何優化伺服器的性能?》,作者: 冰 河 。原文戳→https://bbs.huaweicloud.com/blogs/393407?utm_source=jinritoutiao&utm_medium=bbs-ex&utm_campaign=other&utm_content=content
寫在前面
最近,有小夥伴在群裡提問:Linux系統怎麼設定tcp_nodelay參數?也有小夥伴說問我。那今天,我們就來根據這個問題來聊聊在高并發場景下如何優化伺服器的性能這個話題。
其實,tcp_nodelay參數并不是在作業系統級别進行配置的,而是在TCP套接字上添加tcp_nodelay參數來關閉粘包算法,以便使資料包能夠立即投遞出去。tcp_nodelay參數主要是對TCP套接字來說的,那對于伺服器硬體,如果要使其能夠支撐上百萬甚至上千萬的并發,我們該如何對其進行優化呢?
作業系統
這裡,我使用的作業系統為CentOS 8,我們可以輸入如下指令來檢視作業系統的版本。
CentOS Linux release 8.0.1905 (Core)
對于高并發的場景,我們主要還是優化作業系統的網絡性能,而作業系統中,有很多關于網絡協定的參數,我們對于伺服器網絡性能的優化,主要是對這些系統參數進行調優,以達到提升我們應用通路性能的目的。
系統參數
在CentOS 作業系統中,我們可以通過如下指令來檢視所有的系統參數。
/sbin/sysctl -a
部分輸出結果如下所示。
這裡的參數太多了,大概有一千多個,在高并發場景下,我們不可能對作業系統的所有參數進行調優。我們更多的是關注與網絡相關的參數。如果想獲得與網絡相關的參數,那麼,我們首先需要擷取作業系統參數的類型,如下指令可以擷取作業系統參數的類型。
/sbin/sysctl -a|awk -F "." '{print $1}'|sort -k1|uniq
運作指令輸出的結果資訊如下所示。
abi
crypto
debug
dev
fs
kernel
net
sunrpc
user
vm
其中的net類型就是我們要關注的與網絡相關的作業系統參數。我們可以擷取net類型下的子類型,如下所示。
/sbin/sysctl -a|grep "^net."|awk -F "[.| ]" '{print $2}'|sort -k1|uniq
輸出的結果資訊如下所示。
bridge
core
ipv4
ipv6
netfilter
nf_conntrack_max
unix
在Linux作業系統中,這些與網絡相關的參數都可以在/etc/sysctl.conf 檔案裡修改,如果/etc/sysctl.conf 檔案中不存在這些參數,我們可以自行在/etc/sysctl.conf 檔案中添加這些參數。
在net類型的子類型中,我們需要重點關注的子類型有:core和ipv4。
優化套接字緩沖區
如果伺服器的網絡套接字緩沖區太小,就會導緻應用程式讀寫多次才能将資料處理完,這會大大影響我們程式的性能。如果網絡套接字緩沖區設定的足夠大,從一定程度上能夠提升我們程式的性能。
我們可以在伺服器的指令行輸入如下指令,來擷取有關伺服器套接字緩沖區的資訊。
/sbin/sysctl -a|grep "^net."|grep "[r|w|_]mem[_| ]"
輸出的結果資訊如下所示。
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_default = 212992
net.core.wmem_max = 212992
net.ipv4.tcp_mem = 43545 58062 87090
net.ipv4.tcp_rmem = 4096 87380 6291456
net.ipv4.tcp_wmem = 4096 16384 4194304
net.ipv4.udp_mem = 87093 116125 174186
net.ipv4.udp_rmem_min = 4096
net.ipv4.udp_wmem_min = 4096
其中,帶有max、default、min關鍵字的為分别代表:最大值、預設值和最小值;帶有mem、rmem、wmem關鍵字的分别為:總記憶體、接收緩沖區記憶體、發送緩沖區記憶體。
這裡需要注意的是:帶有rmem 和 wmem關鍵字的機關都是“位元組”,而帶有mem關鍵字的機關是“頁”。“頁”是作業系統管理記憶體的最小機關,在 Linux 系統裡,預設一頁是 4KB 大小。
如何優化頻繁收發大檔案
如果在高并發場景下,需要頻繁的收發大檔案,我們該如何優化伺服器的性能呢?
這裡,我們可以修改的系統參數如下所示。
net.core.rmem_default
net.core.rmem_max
net.core.wmem_default
net.core.wmem_max
net.ipv4.tcp_mem
net.ipv4.tcp_rmem
net.ipv4.tcp_wmem
這裡,我們做個假設,假設系統最大可以給TCP配置設定 2GB 記憶體,最小值為 256MB,壓力值為 1.5GB。按照一頁為 4KB 來計算, tcp_mem 的最小值、壓力值、最大值分别是 65536、393216、524288,機關是“頁” 。
假如平均每個檔案資料包為 512KB,每個套接字讀寫緩沖區最小可以各容納 2 個資料包,預設可以各容納 4 個資料包,最大可以各容納 10 個資料包,那我們可以算出 tcp_rmem 和 tcp_wmem 的最小值、預設值、最大值分别是 1048576、2097152、5242880,機關是“位元組”。而 rmem_default 和 wmem_default 是 2097152,rmem_max 和 wmem_max 是 5242880。
注:後面詳細介紹這些數值是如何計算的~~
這裡,還需要注意的是:緩沖區超過了 65535,還需要将 net.ipv4.tcp_window_scaling 參數設定為 1。
經過上面的分析後,我們最終得出的系統調優參數如下所示。
net.core.rmem_default = 2097152
net.core.rmem_max = 5242880
net.core.wmem_default = 2097152
net.core.wmem_max = 5242880
net.ipv4.tcp_mem = 65536 393216 524288
net.ipv4.tcp_rmem = 1048576 2097152 5242880
net.ipv4.tcp_wmem = 1048576 2097152 5242880
優化TCP連接配接
對計算機網絡有一定了解的小夥伴都知道,TCP的連接配接需要經過“三次握手”和“四次揮手”的,還要經過慢啟動、滑動視窗、粘包算法等支援可靠性傳輸的一系列技術支援。雖然,這些能夠保證TCP協定的可靠性,但有時這會影響我們程式的性能。
那麼,在高并發場景下,我們該如何優化TCP連接配接呢?
(1)關閉粘包算法
如果使用者對于請求的耗時很敏感,我們就需要在TCP套接字上添加tcp_nodelay參數來關閉粘包算法,以便資料包能夠立刻發送出去。此時,我們也可以設定net.ipv4.tcp_syncookies的參數值為1。
(2)避免頻繁的建立和回收連接配接資源
網絡連接配接的建立和回收是非常消耗性能的,我們可以通過關閉空閑的連接配接、重複利用已經配置設定的連接配接資源來優化伺服器的性能。重複利用已經配置設定的連接配接資源大家其實并不陌生,像:線程池、資料庫連接配接池就是複用了線程和資料庫連接配接。
我們可以通過如下參數來關閉伺服器的空閑連接配接和複用已配置設定的連接配接資源。
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time=1800
(3)避免重複發送資料包
TCP支援逾時重傳機制。如果發送方将資料包已經發送給接收方,但發送方并未收到回報,此時,如果達到設定的時間間隔,就會觸發TCP的逾時重傳機制。為了避免發送成功的資料包再次發送,我們需要将伺服器的net.ipv4.tcp_sack參數設定為1。
(4)增大伺服器檔案描述符數量
在Linux作業系統中,一個網絡連接配接也會占用一個檔案描述符,連接配接越多,占用的檔案描述符也就越多。如果檔案描述符設定的比較小,也會影響我們伺服器的性能。此時,我們就需要增大伺服器檔案描述符的數量。
例如:fs.file-max = 10240000,表示伺服器最多可以打開10240000個檔案。
關注#華為雲開發者聯盟#,第一時間了解華為雲新鮮技術~