關于流量升高導致TIME_WAIT增加,MySQL連接大量失敗的問題
搜索有個應用就是每次都會去查一個接口,接口返回用戶的信息數據,從而展現不同的篩選和排序效果。大致流程如下
s.taobao.com(hz)-> memcache ->電信custom接口 ->master-db
s.taobao.com(qd)-> 網通custom接口 -> slave-db
接口環境是php(cgi) + nginx,接口已經運行很久,未出過異常
搜索訪問custom接口,然后接口去查數據庫(數據庫是主從復制,數據同步,各自機房讀各自的數據庫,寫的話都寫master-db)
有一點,就是電信機房是有memcache層的,而網通機房一直沒有(考慮到網通機房流量不高,并且機房cache不同步,從上線起就網通機房一直未使用cache)
有一次搜索上線,這個上線的版本有個改動就是把電信機房的memcache也取消了,然后 電信機房流量暴增
看pv統計:
[admin@linux ~]$ xxx.sh “find ./ -name ‘access*’|xargs wc -l|awk ‘END{print$1}’” fe
cmd :find ./ -name ‘access*’|xargs wc -l|awk ‘END{print }’
type:fe
server1
27720029 total(28號是11428684total)
———-
server2
27719910 total(28號是11429158total)
———-
server3
21084539 總計
———-
server4
21086051 total
網通機房流量一直都是2KW左右,從未出任何問題
就是昨天電信custom接口流量暴增后,出現了異常,電信機房機器負載一度達到48左右,QPS達到1533,直到凌晨0:24分才降到1以下
應用也報了短暫的超時警報,不過php和nginx運行還是比較蛋定,重啟依然非常快,終端也沒有出現很卡的情況
29號流量:
28號流量:
異常就是error.log在上線后飆到3個G?。。?/p>
而且錯誤全都是Can’t connect to MySQL server on ’1.1.1.1′ (99)
即便在命令行下用mysql -h1.1.1.1 -u -p
也間歇性地連接不上,但是據dba描述,數據庫監控無任何異常,數據庫上其他部門的應用也無異常
不知是否機器負載過高導致大量time wait,導致mysql連接超時或連接不上
以下是晚上0點13分的監控:
80端口連接數(CurrentConnection): 16
nginx進程數量: 10
php進程數量: 130
TCP連接狀態:
TIME_WAIT 26258(不知是否和他有關)
FIN_WAIT1 1
FIN_WAIT2 6
ESTABLISHED 893
按理說,custom的網通接口流量一直是日均2KW,從未出現過異常,杭州機房接口飆到2.7KW就抗不住了,load直線上升,
為了排除cache引起的流量導致接口異常,22:30左右重新上了2個文件,把杭州機房的memcache重新開啟,
開啟后慢慢load是降了,但是mysql錯誤依舊只是沒那么多了
現在去機器上看,還是大量錯誤,提取日志如下
2011/12/3010:23:58 [error] 23859#0: *19554416 FastCGI sent in stderr: “PHPWarning: mysql_connect() [
后來跟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:1500+,負載:48+,雖然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 = 1net.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的復用,經驗之談?。?/li>
【編輯推薦】