TCP連線的建立與backlog引數

2021-09-08 21:39:25 字數 1688 閱讀 1733

產品在啟動的時候會建立driver和simulator之間(driver用以驅動simulator的行為以及相互傳遞資訊)的tcp連線用以通訊,而當開始跑業務的時候應用層立即丟擲「connection lost」的錯誤,沒法再繼續跑業務。該問題同樣是出現在產品rhel版本從6.7公升級到7.5後出現的。

起初發現該問題所在的環境是a,driver和simulator的部署如圖1所示,兩者之間連線關係是n:n,可是該問題在a上只能低概率出現。後來在環境b上則可以較高概率地出現,而問題復現的條件也一直沒有摸索出來。環境a和b都是rhel7.5的系統。

圖1

我們嘗試使用tshark工具抓取client端(driver)和server端(simulator)之間的資料報,也許我們可以看到他們它們怎樣斷開連線的,是誰先斷開的等資訊。以server 1上的sim上的資料報為例,發現有多次tcp retransmission以及dup ack,在開始跑業務的時候server給client端傳送了rst訊息,這會直接斷掉連線;後來發現由於軟體應用層的實現,之後driver client將會傳送fin訊息給另外兩個相連的simulator來斷開連線,以圖2中為例:

圖2我們debug除錯時發現在軟體啟動後在這些出現問題的連線中,僅僅有driver側提示tcp連線建立成功(即gen_tcp:connect/3返回),而simulator側並沒有這樣的提示。

根據資料報中的表現找到一篇文章:tcp/ip協議中backlog引數。

我們在simulator側的**中的listen函式找到了backlog引數(5),而其第乙個引數是socket的file description;而linux中對此引數的系統配置值是2048,調整這裡的配置是沒有效果的。增大listen函式的引數後的確解決了這個問題。

所以是因為accpt queue佇列長度過小,服務端沒有足夠的能力去監聽一定規模的連線請求,導致在tcp三次握手時有一部分tcp連線沒有被放入全連線佇列中(客戶端的ack訊息相當於沒有到達服務端),那麼這些連線自始至終都沒有被建立好,而作為客戶端,gen_tcp:connect/3的執行是無法感知這一狀況的。

我們沒有尋求rhel support的幫助,但根據paul所說,大概是rhel7.5上監聽tcp連線建立將使用更長的時間片,而如果在該時間片內出現了上述的情況,系統也無法做出什麼處理,系統只會繼續處理下乙個時間片(包含從連線請求池中獲取的下一批),而這些連線請求將會永久「擱淺」。

在兩個環境中復現此問題的概率有較大差別,我們想這可能是因為a有28個核心來部署driver和simulator,而b有40個,考慮到部署策略,更多的核心數意味著系統在短時間內需要處理更多的tcp連線請求,而若依然使用rhel6.7上的引數是有可能出現問題的。

其實,在應用層上也可以引入乙個略有改善的方案:tcp連線請求重發。在一定時間內如果tcp連線沒有一次性建立成功,可以重新傳送請求,當該請求被放入新的時間片中被重新處理時,應該是可以保證其被成功處理的。

不過嚴格說來這會降低效率,並且不是乙個萬全的方法。

TCP建立連線與釋放連線

tcp建立連線與釋放連線 tcp建立連線與釋放連線 最近複習準備 計算機網路 考試,感覺tcp協議建立連線與釋放連線這兩個過程比較重要,所以把自己理解的部分寫下來。1.建立連線 三次握手 1 客戶端傳送乙個syn包給伺服器,然後等待應答。2 伺服器端回應給客戶端乙個ack 1 syn 1的tcp資料...

TCP建立連線與釋放連線

tcp建立連線與釋放連線 最近複習準備 計算機網路 考試,感覺tcp協議建立連線與釋放連線這兩個過程比較重要,所以把自己理解的部分寫下來。1.建立連線 三次握手 1 客戶端傳送乙個syn包給伺服器,然後等待應答。2 伺服器端回應給客戶端乙個ack 1 syn 1的tcp資料段。3 客戶必須再次回應伺...

TCP建立連線與釋放連線

tcp建立連線與釋放連線 最近複習準備 計算機網路 考試,感覺tcp協議建立連線與釋放連線這兩個過程比較重要,所以把自己理解的部分寫下來。1.建立連線 三次握手 1 客戶端傳送乙個syn包給伺服器,然後等待應答。2 伺服器端回應給客戶端乙個ack 1 syn 1的tcp資料段。3 客戶必須再次回應伺...