最近線上上遇到一個TCP動態埠相關的問題,之前沒有留意過此類問題,做個筆記記錄在這裡,希望也能給大家提供個參考。
簡單介紹下問題的場景:Windows伺服器上,部署了閘道器程式SG和RPC程式,其中RPC程式監聽本地8003埠。問題發生在一次線上常規釋出的時候,RPC程式會重啟一次載入新部署的程式檔案。然而卻啟動失敗了,直接原因是”通常每個套接字地址(協議/網路地址/埠)只允許使用一次。“。於是檢查本地埠占用情況,發現8003埠確實被佔用了,而且是被閘道器程式佔用,如下圖所示。
背景資料
-
TCP/IP協議傳輸層建立連線時請求方和目標方都需要分配一個埠號。目標方的埠號自然是提前分配並建立連線時確定具體埠的,但是請求方的埠就採用本地動態埠的策略隨機分配1個使用。
-
動態埠的分配也不是純隨機的,而是根據OS設定,在一個範圍內隨機。可以通過命令檢視:
netsh int ipv4 show dynamicport tcp
其中啟動埠就是起始埠,埠數就是動態埠可分配的個數。
也可以通過命令設定起始埠和數量:
netsh int ipv4 set dynamicport tcp start=32765 num=30000
- Windows上動態埠的設定不是一成不變的,簡單來說: 在Windows vista和windows server 2008以前的系統中動態的客戶端埠範圍是1025到5000;在Windows vista和windows server 2008中,為了遵守IANA的推薦,把範圍擴充套件成49152到65535。
原因分析
根據以上內容,檢視了伺服器的動態埠配置,發現確實有問題:
也就是說,作為Socket連線請求方的閘道器程式,確實可能會從OS獲取到8003埠準備發起連線,所以RPC程式重啟時再次繫結8003自然就失敗了。
解決方案
修改本地動態埠範圍,避開常用的服務埠範圍。
擴充套件延申
查閱資料時,看到有文章提到埠回收到重用會有時間間隔,根據 RFC793 規範,此值應是網路上最大段生存期的兩倍(2msl),處於這個階段的連線狀態未TIME_WAIT。可以通過登錄檔配置此值,路徑:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters,鍵TcpTimedWaitDelay。