一、背景html
團隊有2臺API服務,使用Resin4佈署的web服務。剛上線調用方很是少,跑了幾個月後,程序正常得很。linux
可是因爲業務的發展,此API要給多個高併發的應用調用,級別在300w/天左右,瞬間請求可去到100+/s。web
本身看服務,其實服務執行狀況還好,雖然請求量高了些,可是程序的成功率很高,CPU有波動,可是算正常。bash
但是後來,調用方運行一段時間後,說有1/3的請求都被拒絕或者超時了。因而在想是否是resin4可支撐的線程數過小。服務器
二、第一次調優cookie
因而修改了resin.properties裏的線程池的大小:網絡
# Throttle the number of active threads for a port port_thread_max : 1024 accept_thread_max : 1024 accept_thread_min : 32
port_thread_max: 每一個端口最多能夠有的活躍線程數,避免系統負載壓力過大。併發
可是觀察了一段時間後,效率不明顯,仍是有拒絕。負載均衡
三、第二次調優socket
就在昨天,發現兩臺服務一直在告警,說服務不可達,其實就是超長時間無響應。
無心中發現2臺服務器的負載狀況不均衡,一臺基本沒有請求到,一臺不少請求。
這個其實跟上層的負載均衡有比較大關係。
可是經過查看系統狀況,發現進程中存在大量的TIME_WAIT。
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 23456 FIN_WAIT1 3 FIN_WAIT2 26 ESTABLISHED 185 SYN_RECV 2 LAST_ACK 1
通過查看如下兩篇文章:
http://kerry.blog.51cto.com/172631/105233/
http://blog.chinaunix.net/uid-24517549-id-4048652.html
其中有說到:
根據TCP協議定義的3次握手斷開鏈接規定,發起socket主動關閉的一方 socket將進入TIME_WAIT狀態,TIME_WAIT狀態將持續2個MSL(Max Segment Lifetime),在Windows下默認爲4分鐘,即240秒,TIME_WAIT狀態下的socket不能被回收使用. 具體現象是對於一個處理大量短鏈接的服務器,若是是由服務器主動關閉客戶端的鏈接,將致使服務器端存在大量的處於TIME_WAIT狀態的socket, 甚至比處於Established狀態下的socket多的多,嚴重影響服務器的處理能力,甚至耗盡可用的socket,中止服務.
因而參考修改:
發現系統存在大量TIME_WAIT狀態的鏈接,經過調整內核參數解決,
vi /etc/sysctl.conf
編輯文件,加入如下內容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
而後執行
/sbin/sysctl -p
讓參數生效。
狀況立刻有好轉,TIME_WAIT迅速降低,Established開始上升並穩定。
---2017年更新---
打開了端口回收,會致使大量鏈接失敗。建議改成如下:
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_timestamps = 1
把這三行加進去/etc/sysctl.conf,而後sysctl -p
而後把linux默認的可用端口號調大。由於默認的端口號爲:
#sysctl -a|grep ip_local_port_range
net.ipv4.ip_local_port_range = 32768 61000
可修改 爲:
net.ipv4.ip_local_port_range = 1024 65535
四、可選優化
鏈接數自己就不少,咱們能夠再優化一下TCP/IP的可以使用端口範圍,進一步提高服務器的併發能力。依然是往上面的參數文件中,加入下面這些配置:
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000這幾個參數,建議只在流量很是大的服務器上開啓,會有顯著的效果。通常的流量小的服務器上,沒有必要去設置這幾個參數。這幾個參數的含義以下:
net.ipv4.tcp_keepalive_time = 1200 表示當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時,改成20分鐘。
net.ipv4.ip_local_port_range = 10000 65000 表示用於向外鏈接的端口範圍。缺省狀況下很小:32768到61000,改成10000到65000。(注意:這裏不要將最低值設的過低,不然可能會佔用掉正常的端口!)
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN隊列的長度,默認爲1024,加大隊列長度爲8192,能夠容納更多等待鏈接的網絡鏈接數。
net.ipv4.tcp_max_tw_buckets = 5000 表示系統同時保持TIME_WAIT的最大數量,若是超過這個數字,TIME_WAIT將馬上被清除並打印警告信息。默 認爲180000,改成5000。對於Apache、Nginx等服務器,上幾行的參數能夠很好地減小TIME_WAIT套接字數量,可是對於 Squid,效果卻不大。此項參數能夠控制TIME_WAIT的最大數量,避免Squid服務器被大量的TIME_WAIT拖死。
五、總結:
因此要多角度考慮,一個軟件的不足,不僅是考慮其自己的問題,還要考慮所處的系統環境。