優(yōu)化Linux下的內(nèi)核TCP參數(shù)以提高系統(tǒng)性能
內(nèi)核的優(yōu)化跟服務(wù)器的優(yōu)化一樣,應(yīng)本著穩(wěn)定安全的原則。下面以Squid服務(wù)器為例來說明,待客戶端與服務(wù)器端建立TCP/IP連接后就會關(guān)閉Socket,服務(wù)器端連接的端口狀態(tài)也就變?yōu)門IME_WAIT了。那是不是所有執(zhí)行主動關(guān)閉的Socket都會進(jìn)入TIME_WAIT狀態(tài)呢?有沒有什么情況可使主動關(guān)閉的Socket直接進(jìn)入CLOSED狀態(tài)呢?答案是主動關(guān)閉的一方在發(fā)送最后一個ACK后就會進(jìn)入TIME_WAIT狀態(tài),并停留2MSL(報文最大生存)時間,這是TCP/IP必不可少的,也就是說這一點(diǎn)是“解決”不了的。
TCP/IP設(shè)計者如此設(shè)計,主要原因有兩個:
- 防止上一次連接中的包迷路后重新出現(xiàn),影響新的連接(經(jīng)過2MSL時間后,上一次連接中所有重復(fù)的包都會消失)。
- 為了可靠地關(guān)閉TCP連接。主動關(guān)閉方發(fā)送的最后一個ACK(FIN)有可能會丟失,如果丟失,被動方會重新發(fā)送FIN,這時如果主動方處于CLOSED狀態(tài),就會響應(yīng)RST而不是ACK。所以主動方要處于TIME_WAIT狀態(tài),而不能是CLOSED狀態(tài)。另外,TIME_WAIT并不會占用很大的資源,除非受到攻擊。
在Squid服務(wù)器中可輸入如下命令查看當(dāng)前連接統(tǒng)計數(shù):
netstat -n | awk '/^tcp/ {++S[$NF]} END{for(a in S) print a, S[a]}'
命令顯示結(jié)果如下所示:
LAST_ACK 14
SYN_RECV 348
ESTABLISHED 70
FIN_WAIT1 229
FIN_WAIT2 30
CLOSING 33
TIME_WAIT 18122
命令中的含義分別如下。
- CLOSED:無活動的或正在進(jìn)行的連接。
- LISTEN:服務(wù)器正在等待進(jìn)入呼叫。
- SYN_RECV:一個連接請求已經(jīng)到達(dá),等待確認(rèn)。
- SYN_SENT:應(yīng)用已經(jīng)開始,打開一個連接。
- ESTABLISHED:正常數(shù)據(jù)傳輸狀態(tài)。
- FIN_WAIT1:應(yīng)用說它已經(jīng)完成。
- FIN_WAIT2:另一邊已同意釋放。
- ITMED_WAIT:等待所有分組死掉。
- CLOSING:兩邊嘗試同時關(guān)閉。
- TIME_WAIT:另一邊已初始化一個釋放。
- LAST_ACK:等待所有分組死掉。
也就是說,這條命令可以把當(dāng)前系統(tǒng)的網(wǎng)絡(luò)連接狀態(tài)分類匯總。
在Linux下高并發(fā)的Squid服務(wù)器中,TCP TIME_WAIT套接字的數(shù)量經(jīng)常可達(dá)到兩三萬,服務(wù)器很容易就會被拖死。不過,可以通過修改Linux內(nèi)核參數(shù)來減少Squid服務(wù)器的TIME_WAIT套接字?jǐn)?shù)量,命令如下:
vim /etc/sysctl.conf
然后,增加以下參數(shù):
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
以下將簡單說明上面各個參數(shù)的含義:
- net.ipv4.tcp_syncookies=1表示開啟SYN Cookies。當(dāng)出現(xiàn)SYN等待隊列溢出時,啟用Cookie來處理,可防范少量的SYN攻擊。該參數(shù)默認(rèn)為0,表示關(guān)閉。
- net.ipv4.tcp_tw_reuse=1表示開啟重用,即允許將TIME-WAIT套接字重新用于新的TCP連接。該參數(shù)默認(rèn)為0,表示關(guān)閉。
- net.ipv4.tcp_tw_recycle=1表示開啟TCP連接中TIME-WAIT套接字的快速回收,該參數(shù)默認(rèn)為0,表示關(guān)閉。
- net.ipv4.tcp_fin_timeout=30表示如果套接字由本端要求關(guān)閉,那么這個參數(shù)將決定它保持在FIN-WAIT-2狀態(tài)的時間。
- net.ipv4.tcp_keepalive_time=1200表示當(dāng)Keepalived啟用時,TCP發(fā)送Keepalived消息的頻度改為20分鐘,默認(rèn)值是2小時。
- net.ipv4.ip_local_port_range=1000065000表示CentOS系統(tǒng)向外連接的端口范圍。其默認(rèn)值很小,這里改為10000到65000。建議不要將這里的最低值設(shè)得太低,否則可能會占用正常的端口。
- net.ipv4.tcp_max_syn_backlog=8192表示SYN隊列的長度,默認(rèn)值為1024,此處加大隊列長度為8192,可以容納更多等待連接的網(wǎng)絡(luò)連接數(shù)。
- net.ipv4.tcp_max_tw_buckets=5000表示系統(tǒng)同時保持TIME_WAIT套接字的最大數(shù)量,如果超過這個數(shù)字,TIME_WAIT套接字將立刻被清除并打印警告信息,默認(rèn)值為180000,此處改為5000。對于Apache、Nginx等服務(wù)器,前面介紹的幾個參數(shù)已經(jīng)可以很好地減少TIME_WAIT套接字的數(shù)量,但是對于Squid來說,效果卻不大,有了此參數(shù)就可以控制TIME_WAIT套接字的最大數(shù)量,避免Squid服務(wù)器被大量的TIME_WAIT套接字拖死。
執(zhí)行以下命令使內(nèi)核配置立馬生效:
/sbin/sysctl –p
如果是用于Apache或Nginx等Web服務(wù)器,則只需要更改以下幾項(xiàng)即可:
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 10000 65000
執(zhí)行以下命令使內(nèi)核配置立馬生效:
/sbin/sysctl –p
如果是Postfix郵件服務(wù)器,則建議內(nèi)核優(yōu)化方案如下:
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 10000 65000
kernel.shmmax = 134217728
執(zhí)行以下命令使內(nèi)核配置立馬生效:
/sbin/sysctl –p
當(dāng)然這些都只是最基本的更改,大家還可以根據(jù)自己的需求來更改內(nèi)核的設(shè)置,比如我們的線上機(jī)器在高并發(fā)的情況下,經(jīng)常會出現(xiàn)“TCP:too many orpharned sockets”的報錯盡量也要本著服務(wù)器穩(wěn)定的最高原則。如果服務(wù)器不穩(wěn)定的話,一切工作和努力就都會白費(fèi)。如果以上優(yōu)化仍無法滿足工作要求,則有可能需要定制你的服務(wù)器內(nèi)核或升級服務(wù)器硬件。