首頁 > 軟體

GNU Linux高並行效能優化方案

2020-06-16 17:57:39

/***********************************************************
* Author : Samson
* Date : 07/14/2015
* Test platform:
* gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
* GNU bash, 4.3.11(1)-release (x86_64-pc-linux-gnu)
* Nginx version:
* Nginx 1.6.2
* Nginx 1.8.0
* *********************************************************/

GNU Linux高並行效能優化方案

在GNU Linux系統中,影響連線個數的因素主是由於單個進程能夠開啟的最大檔案數、埠數量決定的;而一個基於tcp的伺服器的並行,除了上文說過的兩個因素外,還有因為主要的tcp連線的很多屬性,而問題最大的則是連線斷開後的連線會在TIME_WAIT狀態一直存在60秒,這就造成了在大量高並行的情況下當連線為此TIME_WAIT狀態時沒有可用連線。

1、修改埠號範圍:
預設範圍:

cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000

眾所周知,埠號的範圍為0~65535,知名埠號介於1~255之間,256~1023之間的埠號通常都是由系統占用,所以我們需要更多可以使用的埠號的話,那麼就需要修改系統中對埠使用範圍變數;

修改方法:
1)、echo “1024 65535” > /proc/sys/net/ipv4/ip_local_port_range
2)、在/etc/sysctl.conf中進行如下的設定:
net.ipv4.ip_local_port_range=1024 65535
然後執行: sysctl -p 對這些設定進行生效;

3)、直接使用命令進行系統變數的優化
sysctl -w net.ipv4.ip_local_port_range=1024 65535

若埠不夠用的時候報錯資訊
若沒有空閒的埠可以使用時,將會報錯,如:
connect() to ip:80 failed (99: Cannot assign requested address)

注意:
修改了埠的範圍後,若是有多個服務在一台裝置上時,若是先被其它服務先行啟動將另外的服務的“眾所周知”的埠給占用了,那麼這個問題就比較不太好處理,在這種情況下,對於需要監聽的服務進行先行啟動,將服務要使用的“眾所周知”的埠先行佔用,就不會發生比較麻煩的情況了。

2、修改系統所有進程能夠開啟的檔案數:
cat /proc/sys/fs/file-max
203466

若要修改的話:
echo 403466 > /proc/sys/fs/file-max

3、對於處理TIME_WAIT的問題,通過設定以下兩項可以極大地提高並行
在進行了通訊完畢後,完成通訊的連線差不多在秒級間就進行了回收,經測試,再使用netstat -ntp,都不會再看到剛才使用的連線,但是在官方文件中說明了(Default value is 0. It should not be changed without advice/request of technical experts.)使用這兩種方式需要非常謹慎;如下(修改方法請參看上面的修改方式):
net.ipv4.tcp_tw_reuse = 1

//表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP連線,預設為0,表示關閉;
net.ipv4.tcp_tw_recycle = 1
//表示開啟TCP連線中TIME-WAIT sockets的快速回收,預設為0,表示關閉。

由於以上兩項在官方文件中有這樣的描述”It should not be changed without advice/request of technical experts.“,也即是說,這兩項在某些情況下會產生負作用或影響;

可能出現的影響:
net.ipv4.tcp_tw_recycle是與net.ipv4.tcp_timestamps是密切相關的,而net.ipv4.tcp_timestamps預設是開啟的,當tcp_tw_recycle和tcp_timestamps同時開啟時會啟用TCP的一種隱藏屬性:快取連線的時間戳。60秒內,同一源IP的後續請求的時間戳小於快取中的時間戳,核心就會丟棄該請求。

什麼樣的場景會使時間戳會小於快取中的時間戳呢?
類似的故障場景:
多個用戶端通過一個NAT存取一台伺服器,因為NAT只改IP地址資訊,但不會改變timestamp(TCP的時間戳不是系統時間,而是系統啟動的時間uptime,所以兩台機器的的TCP時間戳一致的可能性很小),那麼就會出現請求被丟棄的情況,所以很容易造成連線失敗的情況。
伺服器上開啟了tcp_tw_recycle用於TIME_WAIT的快速回收故障現象和分析步驟:
1) 通過NAT出口的多個用戶端經常請求Web伺服器無響應;
2) 在伺服器抓包,發現伺服器端可以收到用戶端的SYN請求,但是沒有回應SYN,ACK,也就是說核心直接將包丟棄了。

解決方法:
1) 關閉服務其端的tcp_timestamps,故障可以解決,但是這麼做存在安全和效能隱患,強烈建議不關閉此變數;
2) 關閉tcp_tw_recycle,故障也可以解決。推薦NAT環境下的機器不要開啟該選項;
3)調整網路拓撲避免NAT的這種類似的情況;
4)用戶端使用同一個NTP服務進行時間同步,使時間同步避免timestamp差異;

其它優化引數
net.ipv4.tcp_fin_timeout = 30
//表示如果通訊端由本端要求關閉,這個引數決定了它保持在FIN-WAIT-2狀態的時間。
net.ipv4.tcp_keepalive_time = 1200
//表示當keepalive起用的時候,TCP傳送keepalive訊息的頻度。預設是2小時,改為20分鐘。
net.ipv4.tcp_max_tw_buckets = 5000
//表示系統同時保持TIME_WAIT通訊端的最大數量,如果超過這個數位,
//TIME_WAIT通訊端將立刻被清除並列印警告資訊。預設為180000,改為5000。
//對於Apache、Nginx等伺服器,上幾行的引數可以很好地減少TIME_WAIT通訊端數量,

//此值和/proc/sys/net/ipv4/tcp_max_syn_backlog是一樣的,也是對listen()函數中的backlog引數的限制,按照文件中的說明,應該最好是設定成和/proc/sys/net/ipv4/tcp_max_syn_backlog一樣的值,此值的預設值是128:
cat /proc/sys/net/core/somaxconn
128
net.core.somaxconn = 40000

//指定未完成連線佇列的最大長度,預設為1024個,是對socket的listen()函數中的backlog數量的限制,若伺服器過載可以增大此值;
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
1024
net.ipv4.tcp_max_syn_backlog = 40000

4、調整每個進程最大開啟檔案描述符限制
調整檔案描述符限制:

$ ulimit -n
1024
修改此值,ulimit -n 4096

$vi /etc/security/limits.conf
//Setting Shell Limits for File Descriptors
*soft nofile 8192
*hard nofile 8192

這二者的區別,在/etc/security/limits.conf組態檔中設定好後,進行重新啟動後再次使用ulimit -n將得到的值是8192.

5、通過重新編譯核心程式碼減少TCP連線的TIME-WAIT時間
在核心程式碼中的include/net/tcp.h檔案中,TIME-WAIT的定義如下:
//#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
* state, about 60 seconds */
可以通過修改TCP_TIMEWAIT_LEN的值,來加快連線的釋放;修改後,核心進行編譯後進行替換。

Nginx的設定與系統環境變數間的關係
系統預設的是1024,若在Nginx的組態檔中,設定了worker_connections 4096;後,再啟動時,會出現這樣的一個警告:
nginx: [warn] 4096 worker_connections exceed open file resource limit: 1024
Nginx中的這些和系統變數有關的,是根據系統中的設定而進行設定的,若大於了系統變數的範圍的話,不會生效,會被預設成系統的值,如每個worker進行能夠開啟的檔案數量就被預設成系統的值1024;

注意:
修改核心變數是有風險的,最好是在測試環境進行測試通過,再將設定平移到生產環境。

REF:
IPV4和IPV6的核心引數各項的意義及取值:
https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
關於/proc目錄下的主要項的介紹:
http://man7.org/linux/man-pages/man5/proc.5.html

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-07/119962.htm


IT145.com E-mail:sddin#qq.com