Linux網路埠耗盡
我已經在這方面做了盡可能多的研究,而沒有直接探勘核心原始碼。關於這個主題似乎有大量虛假資訊/不正確資訊,所以我希望這能一勞永逸地回答我和其他人的問題。
嚴格來說是 IPv4,埠耗盡真的可能嗎?讓我解釋:
- 似乎有 65535 個埠可供使用。0 不可用。
- 我讀過埠耗盡要求 (src ip, src port, dst ip, dst port) 元組是唯一的。
- 為了清楚起見,假設我可以通過 sysctl net.ipv4.ip_local_port_range 設置使用 100% 的臨時埠
這就是問題:它是這樣工作的嗎?
- 我可以從 127.0.0.1:(x) 到 127.0.0.1:80 有 65k 個連接
- 我可以有 65k 連接,從 127.0.0.1:(x) 到 127.0.0.1:555
- 基本上再一次,問題是 (srcip,srcport,dstip,dstport) 必須是唯一的,對嗎?
- 我無法打開從ip“A”到 IP“B”、埠“N”的超過 65k 個連接
- 同樣,單個 IP無法在 xxxx:80 打開與我的網路伺服器的超過 65k 的連接,但是只要它們來自不同的源 IP ,我就可以支持超過 65k 的總體連接?
最後,我對(傳出)臨時埠和正在偵聽的傳入埠有點困惑。我意識到一旦建立連接,連接的每一端都是對等且平等的,但在此之前:
例如,如果確實 (srcip,srcport,dstip,dstport) 元組必須是唯一的,為什麼如果我啟用它,例如
net.ipv4.ip_local_port_range = 1024 65535
這允許使用 1024-65535 的臨時埠,如果我有綁定在埠 3306 上的服務(例如 mySQL),它們有時會因為埠正在使用而無法啟動。
這是否與以下事實有關:(這是我要求驗證的聲明):
- (srcip,srcport,dstip,dstport) 對於每個埠範圍為 1-65535 的連接需要是唯一的(不注意作業系統對臨時埠的使用)
- 但是,對於要綁定的套接字,它可以被視為 (srcip,srcport, *, *)。或者換一種說法,IP是否一定不能出於任何原因使用該埠來綁定?
我可以驗證上述行為,即我使用上面的確切 sysctl 行,因此我將 mySQL 移動到低於 1024 的埠,因為它偶爾會非常隨機地無法重新啟動,因為假設作業系統正在使用該埠(3306)對於臨時埠。
您在這裡有兩個主要問題:
1.
嚴格來說是 IPv4,埠耗盡真的可能嗎?
是的。例如,負載平衡路由器將所有連接發送到 NAT IP 地址。當您有許多
SRC IP
連接到單個DST IP
.這意味著您的網路伺服器可能有一堆連接,例如:
root@buglab:~# netstat -pnt Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 173.200.1.18:80 10.100.1.100:49923 ESTABLISHED 13939/nginx: worker tcp 0 0 173.200.1.18:80 10.200.1.200:10155 ESTABLISHED 13939/nginx: worker tcp 0 0 173.200.1.18:80 10.10.1.10:14400 ESTABLISHED 13939/nginx: worker tcp 0 0 173.200.1.18:80 10.10.1.10:50652 ESTABLISHED 13939/nginx: worker tcp 0 0 173.200.1.18:80 10.20.1.20:57554 ESTABLISHED 13939/nginx: worker
這很好。但是,如果所有“外國地址”都相同,這可能會導致問題(例如,“使用一個 IP 地址執行 NAT <—> 伺服器的大型路由器”)。
如果我不得不假設為什麼短暫埠耗盡不是一個常見問題,我建議這是因為每個埠都需要一個監聽服務和足夠的資源來響應——另一個資源(記憶體、cpu)通常首先是一個瓶頸。
但是,在負載平衡公司工作時,我個人遇到了一些埠耗盡問題。
2. 為什麼使用的埠會給監聽服務帶來問題?
“這允許使用 1024-65535 的臨時埠,如果我有綁定在埠 3306 上的服務(例如 mySQL),它們有時會因為埠正在使用而無法啟動。”
如果該埠正在使用中,則 mySQL 伺服器無法綁定到該埠 - 例如通過 localhost:3306 或在所有介面上。例如,看到以下
netstat
輸出中的 0.0.0.0:80 行?root@buglab:~# netstat -lnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 964/php-fpm.conf) tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 1660/mysqld tcp 0 0 0.0.0.0:842 0.0.0.0:* LISTEN 1317/inetd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 13938/nginx
這意味著埠 80 正在偵聽伺服器本地的所有介面。
nginx
如果另一個程序在我的伺服器啟動之前持有埠 80 ,nginx
將無法控制該埠,並且可能會導致其啟動過程失敗。通常,埠 3306 很好,因為偵聽服務具有從主機請求的預定義埠(或範圍)——例如用於網路伺服器的埠 80 和 443。