有個應用就是每次都會去查一個介面,介面返回使用者的資訊資料,從而展現不同的頁面效果。大致流程如下
應用APP(電信)-> memcache ->電信custom介面 ->master-db
應用APP(網通)-> 網通custom介面 -> slave-db
介面環境是php(cgi) + nginx,介面已經運行很久,未出過異常
應用訪問custom介面,然後介面去查資料庫(資料庫是主從複製,資料同步,各自機房讀各自的資料庫,寫的話都寫master-db)
有一點,就是電信機房是有memcache層的,而網通機房一直沒有(考慮到網通機房流量不高,並且機房cache不同步,從上線起就網通機房一直未使用cache)
有一次上線,這個上線的版本有個改動就是把電信機房的memcache也取消了,然後 電信機房流量暴增
看pv統計:
[xxx@XXXXXX ~]$xxx.sh "find /path -name 'access*'|xargs wc -l|awk 'END{print$1}'" fe
cmd :find /path 'access*'|xargs wc -l|awk 'END{print }'
type:fe
server1
2倍A total(28號是Atotal)
-----------
server2
2倍B(28號是B
total)
-----------
server3
C 總計
-----------
server4
D total
....
other servers ....
網通機房流量一直比較穩定左右,從未出任何問題
就是昨天電信custom介面流量暴增後,出現了異常,電信機房機器負載漲了40多倍,QPS漲了15倍,直到淩晨0:24分才降到1以下
應用也報了短暫的逾時警報,不過php和nginx運行還是比較蛋定,重啟依然非常快,終端也沒有出現很卡的情況
流量是前一天的9倍!
異常就是error.log在上線後飆到3個G!!!
而且錯誤全都是Can't connect to MySQL server on '1.1.1.1' (99)
即便在命令列下用mysql -hx.x.x.x
-u -p
也間歇性地串連不上,但是據dba描述,資料庫監控無任何異常,資料庫上其他部門的應用也無異常
不知是否機器負載過高導致大量time wait,導致mysql連線逾時或串連不上
以下是晚上0點13分的監控:
TIME_WAIT 漲了300倍(不知是否和他有關)
ESTABLISHED 漲了10倍
按理說,custom的網通介面流量非常穩定,從未出現過異常,電信機房介面飆了2倍就抗不住了,load直線上升,
為了排除cache引起的流量導致介面異常,22:30左右重新上了2個檔案,把電信機房的memcache重新開啟,
開啟後慢慢load是降了,但是mysql錯誤依舊只是沒那麼多了
現在去機器上看,還是大量錯誤,提取日誌如下
FastCGI sent in stderr: "PHPWarning: mysql_connect()Can't connect to MySQL server on '1.1.1.1' (99)in XXXXXX on line xxx
後來跟dba不斷溝通排查,發現電信機房和網通機房的/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= 5
原因就在這,把配置同步到杭電信機房後,問題就解決了,總結如下:
- 問題描述
- 上線異常導致qps:五倍+,負載:四十倍+,雖然nginx+php表示很淡定沒掛,但error.log飆到了3G/天,全是Can’t connect to MySQL server on ‘*.*.*.*’ (99)
- 解決異常後,error.log日誌少了,但TIME_WAIT依舊減不下去,資料庫依舊串連是失敗
- 問題排查
- Mysql Config ? (no problem)
- max_connect_errors = 50000 (no problem)
- max_connections = 1000 (no problem)
- max_user_connections = 950 (no problem)
- OS Config ? (problem, 按以下修改問題就解決了)
- 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 = 5
// 讓參數生效
/sbin/sysctl -p
- 問題原因
- 報錯”Can’t connect to MySQL server on ‘*.*.*.*’ (99) ” 參考MySQL Client端錯誤碼說明:錯誤碼為99,99的含義:$perror
99 OS error code 99: Cannot assign requested address 這是一個本地OS的拋錯,表示無法分配本地地址資源(應該是連接埠),socket無法建立
- Google一下” Cannot assign requested address”,多半是由於用戶端請求過於頻繁,而Server端練級關閉後本地暫時處於TIME_WAIT,所以暫時連接埠都不可用導致。因此修改下OS參數就ok了
- 問題反思
- 這個問題非常緊急嗎?緊急!
- 參考文章《nginx+php產生大量TIME_WAIT》:http://leven.blog.51cto.com/1675811/382097,遇到這樣的問題,我們應該第一時間想到連接埠不可用,首先會導致nginx連不上php-cgi導致服務不可用,其次才是php-cgi連不上mysql,因此非常重要!
- 為什麼mysql不使用長串連pconnection呢?
- pconnection mysql佔用大量資源,並且在大並發情況下,例如個人化,活動促銷等,串連過多導致無數的串連失敗error,並牽制apache(nginx)ThreadsPerChild的參數
- 高並發下的最佳實務?
- apache短串連,nginx短串連,mysql短串連,雖然TIME_WAIT多了,但可通過修改OS核心加速TIME_WAIT的複用,經驗之談啊!