服務器維護中處理高并發導致的一些常見問題解決方案
這里還是按照場景來吧,畢竟場景是最能體驗實用性的。首先說下服務器配置以及環境
阿里云ECS云主機,8G內存,4核的CPU,20M帶寬,20G系統盤+200G數據盤,CentOS 6.5 64位,安裝的一件集成lnmp環境
場景:微信發紅包
這個場景是很常見的,一般客戶會在整點的時候進行一次微信公眾號的廣告推送,這兒時候服務器的并發大概在3000到5000左右。說起來這其實并不算是高并發,但是服務器還是崩了,大概需要等待5分鐘之后才能恢復正常。這有點不應該啊,分析原因。查看CPU的利用率并不高,內存使用也很正常,在阿里云控制面板里面查看網絡出口流量滿載,問題大概是清楚了,網絡原因導致。
首先查看靜態資源,發現圖片大部分沒有優化,于是脫下來進行無損壓縮,大概省略了1M左右的大小,提交上去后依然崩潰,服務器頻繁出現502。
再次檢查頁面的靜態資源css和js,把常用的js庫替換成CDN以減少請求數,提交后依然沒有多少變化,502依舊。
于是查看nginx連接數,使用命令
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
結果顯示
TIME_WAIT 3828 SYN_SENT 1 FIN_WAIT1 107 FIN_WAIT2 27 ESTABLISHED 661 SYN_RECV 23 CLOSING 15 LAST_ACK 284
乖乖,TIME_WAITE很高,這里務必說下TIME_WAITE的含義:TIME_WAIT:另一邊已初始化一個釋放。這個是啥意思呢?意思就是服務器已經主動關閉了,在等待客戶端給一個回應,如果客戶端一直沒有回應就會出現等待,這個值就會增加。很顯然,這個時候我們需要減少 TIME_WAIT的值。
這里只需要修改sysctl.conf的一些參數即可,編輯/etc/sysctl.conf文件,檢查
net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_tw_reuse=1 #讓TIME_WAIT狀態可以重用,這樣即使TIME_WAIT占滿了所有端口,也不會拒絕新的請求造成障礙 默認是0 net.ipv4.tcp_tw_recycle=1 #讓TIME_WAIT盡快回收 默認0 net.ipv4.tcp_fin_timeout=30
是否是這樣的設置,如果找不到對應的,在文件最后加上即可。保存后執行
/sbin/sysctl -p
配置即可生效。
20分鐘后繼續查看nginx連接數,結果
TIME_WAIT 87 SYN_SENT 1 FIN_WAIT1 60 FIN_WAIT2 19 ESTABLISHED 477 SYN_RECV 12 CLOSING 2 LAST_ACK 100
恢復正常,網絡帶寬也降下來了。
但是好景不長,第二次整點開始搶紅包的時候又出現了502。查看進程發現mysqld的CPU占用率很高,導致CPU滿載,服務器崩潰。修改 mysql配置文件,調整max_connection為30000。其他相關參數進行了調整優化,情況有所緩解,但是短短幾分鐘之內CPU又滿載了。
詭異!于是查看mysql中的進程,發現頻繁的sql查詢,而所查詢的幾個表數據量均在10萬左右,判斷是因為沒有設置索引導致。咨詢后端開發,果然是只設置了主鍵。立刻修改,提交上去五分鐘后CPU降下來,穩定在10%左右,也沒有出現過502了。
第二天一早,反饋說服務器很卡,查看帶寬并沒有占用太高。CPU也不高,但是內存卻幾乎耗盡。于是推測碎片太多,清理之。見帖子《Linux內存清理命令》