對于MySQL來說傳回的錯誤代碼為99:
perror 99
Cannot assign requested address (在出現這樣的問題的時候,可以先ulimit -a 看看哪些參數設定的過于嚴格)
這個是程式端容易出現的問題,由于每次連接配接都在很短的時間内結束,導緻很多的TIME_WAIT,以至于用光了可用的端口号,是以新的連接配接沒辦法綁定端口。
核心參數net.ipv4.ip_local_port_range 控制可用的端口數量:
sysctl -a | grep port
net.ipv4.ip_local_port_range = 32768 61000
1
<code>netstat</code> <code>-nt | </code><code>awk</code> <code>'/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'</code>
檢測代碼如上:
我們可以試着分析下TCP端開連接配接的四次握手:
1. 發起方更改狀态為FIN_WAIT_1,關閉應用程式程序,發出一個TCP的FIN段;
2. 接收方收到FIN段,傳回一個帶确認序号的ACK,同時向自己對應的程序發送一個檔案結束符EOF,同時更改狀态為CLOSE_WAIT,發起方接到ACK後狀态更改為FIN_WAIT_2;
3. 接收方關閉應用程式程序,更改狀态為LAST_ACK,并向對方發出一個TCP的FIN段;
4. 發起方接到FIN後狀态更改為TIME_WAIT,并發出這個FIN的ACK确認.ACK發送成功後(2MSL内)雙方TCP狀态變為CLOSED.
TIME_WAIT狀态還需要等2MSL後才能傳回到CLOSED狀态的原因?
這是因為雖然雙方都同意關閉連接配接了,而且握手的4個封包也都協調和發送完畢,按理可以直接回到CLOSED狀态(就好比從SYN_SEND狀态到ESTABLISH狀态那樣);但是因為我們必須要假想網絡是不可靠的,你無法保證你最後發送的ACK封包會一定被對方收到,是以對方處于LAST_ACK狀态下的SOCKET可能會因為逾時未收到ACK封包,而重發FIN封包,是以這個TIME_WAIT狀态的作用就是用來重發可能丢失的ACK封包。
大量的處于TIME_WAIT狀态的socket, 甚至比處于Established狀态下的socket多的多,嚴重影響伺服器的處理能力,甚至耗盡可用的socket,停止服務.處理辦法有以下兩種方式:
1、增加端口号數量
2、減少TIME_WAIT連接配接狀态
linux下:
通過調整核心參數解決,vim /etc/sysctl.conf,加入
net.ipv4.tcp_syncookies = 1 #表示開啟SYN Cookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防範少量SYN攻擊,預設為0,表示關閉;
net.ipv4.tcp_tw_reuse = 1 #表示開啟重用。允許将TIME-WAIT sockets重新用于新的TCP連接配接,預設為0,表示關閉;
net.ipv4.tcp_tw_recycle = 1 #表示開啟TCP連接配接中TIME-WAIT sockets的快速回收,預設為0,表示關閉。
net.ipv4.tcp_fin_timeout = 3 #修改系統預設的 TIMEOUT 時間
net.ipv4.tcp_max_tw_buckets = 10000#通過設定它,系統會将多餘的TIME_WAIT删除掉,此時系統日志裡可能會顯示:『TCP: time wait bucket table overflow』,多數情況下不用在意這些資訊。
/sbin/sysctl -p 讓參數生效。
本文轉自 位鵬飛 51CTO部落格,原文連結:http://blog.51cto.com/weipengfei/1329821,如需轉載請自行聯系原作者