Linux下偵聽端口被占用,怎么解決?
本文轉載自微信公眾號「Linux開發那些事兒」,作者LinuxThings。轉載本文請聯系Linux開發那些事兒公眾號。
不知道你有沒有遇到過這種問題:在同一臺物理機器上,服務A 啟動時偵聽 端口1 ,同時它也作為客戶端去連接 服務B,連接服務B時候會隨機一個端口號,假如隨機的是 端口2 ,這個時候 服務C 正在啟動中,它發現需要偵聽的端口號已經被 服務A的隨機端口 ( 端口號2 ) 占用了,導致服務C 啟動失敗
上述的問題是 服務器 偵聽的端口 被客戶端隨機的端口給占用掉了,導致服務器無法啟動,接下來將介紹 這種情況出現的原因以及如何解決該問題
如何隨機端口號
要弄清楚問題的原因,先需要了解下系統是如何隨機端口號的
Linux 下 /proc/sys/net/ipv4/ip_local_port_range 定義了本地端口的范圍,此文件有兩個整形參數,分別表示本地最小端口號和最大端口號
客戶端調用 connect 函數連接服務器的時候,操作系統會從本地端口范圍中隨機一個沒有使用的端口,作為本次連接的源端口號,如果沒有可用的隨機端口,則連接出錯
在早期的 Linux 版本中,本地端口范圍是從 1024 到 5000 ,總共有 3976 個端口可用,隨著網絡應用的不斷增多,并發連接也會達到新的量級,端口范圍可能會不夠用,所以,新的 Linux 版本調整了本地端口的范圍
下面是在 Linux 3.10 下查看的結果
- [root@cghost22 ~]# cat /proc/sys/net/ipv4/ip_local_port_range
- 32768 61000
注意:1024 以下的端口是系統保留端口,如果想修改 ip_local_port_range 中的端口, 確保都要大于1024
如何解決
通過對隨機端口的了解以及對問題的分析,有以下幾種解決方案
- 調整服務器啟動順序
前面提到,服務A 作為客戶端先連接 服務B,客戶端隨機的源端口 和 服務C 的偵聽端口重復了,導致 服務C 偵聽失敗
如果是這樣,那么調整下服務啟動順序,讓 服務C 在 服務A 之前啟動,這樣就能保證 服務C 先偵聽端口,后面 服務A 再隨機端口就不會和 服務C 的偵聽端口 重復了
讓 某些服務 需要先于另一些 服務 啟動,會增加 服務 之間的耦合度,在設計中需要盡量避免這么做
退一步說,即使這么做了,如果后面 服務C 重啟,在它重啟的過程中,服務A 恰好正在重新連接 服務B, 此時還是有可能出現 服務A 隨機的端口 和 服務C 的 偵聽端口重復,當該端口 先被 服務A 使用了,那么 服務C 還是會偵聽失敗的
- 修改偵聽端口
從上面 隨機端口 小節可知,偵聽端口 和 隨機端口出現重復的原因是 偵聽端口剛好處于 隨機端口的范圍中,所以隨機端口才有幾率出現和偵聽端口相同
只要修改下 偵聽端口 ,使之不會出現在 隨機端口范圍中,比如:把隨機端口范圍設置為 32768-61000,再把偵聽端口設置為 1024-32767 之間的一個值, 這樣隨機端口 和 偵聽端口 就不會出現重復了
如此做確實能解決問題,但是 修改 服務 的偵聽端口,跟該 服務 有邏輯關系上下游都需要做相應的調整,如果項目已經上線了,還需要走一套發布更新流程,需要花費不少時間,如果項目還在開發中,可以直接修改偵聽端口
- 設置本地保留端口
這種方法是將 偵聽端口 添加到 本地保留端口列表中,系統在隨機端口的時候,會過濾掉本地保留端口列表中配置的端口號, 服務只需要做任何改動,只需要重啟下端口重復了的兩個 服務 即可
本地保留端口的配置位于 /proc/sys/net/ipv4/ip_local_reserved_ports , 它支持端口范圍以及單個端口號的配置,單個端口號之間用逗號分隔,端口范圍的最小值和最大值之間用 "-" 符號分隔
例如:50001,5200-5300,6001 表示 本地保留的是 5001,5200 到 5300,6001 這些端口
不過,如果直接配置 /proc/sys/net/ipv4/ip_local_reserved_ports 文件的話,重啟機器之后配置會失效,要想重啟機器依然生效,直接配置 /etc/sysctl.conf
下面是配置本地保留的 5001,5200 到 5300,6001 端口的實例
用 vim 編輯 /etc/sysctl.conf ,在文件末尾添加以下行
- net.ipv4.ip_local_reserved_ports=5001,5200-5300,6001
再執行 sysctl -p 命令重載 /etc/sysctl.conf 配置
小結
本文介紹了 Linux 下隨機端口和偵聽端口重復的原因以及解決方法,雖然可以通過設置本地保留端口來解決,但這畢竟需要多一步配置操作,而且如果服務遷移到其他機器或者當前機器上有服務使用新的偵聽端口,還得添加到本地保留端口中,所以,這種方法比較適合線上緊急處理,比較推薦的做法還是修改下偵聽端口,確保偵聽端口不在隨機端口范圍內