包拯斷案 | 程式連線頻繁出現超時怎麼破@還故障一個真相

萬里資料庫發表於2024-02-02


提問:作為DBA運維的你是否有過這些苦惱


1)資料庫部署完成後,測試時發現程式連線頻繁出現連線超時的情況?


2)每次遇到該問題,應用程式重連後基本能連上,檢查資料庫叢集未出現異常,但嚴重影響測試及上線進度,不知是什麼原因?




## 心中有章,遇事不慌


作為DBA的你,遇到問題無從下手,除了在問題面前徘徊,還能如何選擇?如果你一次或多次遇到該問題還是無法解決,又很懊惱,該如何排憂呢?關注公眾號,關注《包拯斷案》專欄,讓小編為你排憂解難~


## 包拯秘籍

一整套故障排錯及應對策略送給你,讓你像包拯一樣斷案如神:

#首先

遇到此類問題後 我們要做到心中有章(章程),遇事不慌。一定要冷靜,仔細瞭解故障現象(與研發/使用者仔細溝通其反饋的問題,瞭解故障現象、操作流程、資料庫架構等資訊)


#其次

我們要根據故障現象進行初步分析。心中要想:什麼情況會導致程式連線頻繁出現連線超時?例如:是裝置狀態還是配置引數的問題?


#然後

針對上述思考,我們需要逐步驗證並排除,確定問題排查方向。


#接著

確定了問題方向,進行具體分析。透過現象得出部分結論,透過部分結論繼續排查並論證。


#最後

針對問題有了具體分析後,再進行線下復現,最終梳理故障報告。



## 真刀實戰我們能贏


說了這麼多理論,想必實戰更讓你心動。那我們就拿一個真實案例進行分析---


2.1故障處理場景


在專案現場兢兢業業趕進度的你,正在為某個客戶部署了一套安全資料庫GreatDB分散式,卻在應用測試階段,發現程式連線頻繁出現連線超時的情況,經過多次重連後雖然恢復了連線,卻影響了測試進度,對現場情況和原因不太清楚。


2.2 故障處理


客戶現場部署GreatDB分散式叢集,應用需要連線叢集排程節點進行讀寫請求。有三個呼叫節點均可接收應用請求,使用了客戶側提供的F5裝置做負載均衡。透過F5地址連線資料庫叢集頻繁出現連線超時退出等情況,直接連線資料庫排程節點物理IP地址無法復現。


1)問題復現


• 編寫指令碼分別透過F5地址和每個排程節點實際地址測試登入資料庫叢集;


• 發現只有透過F5連線時才能復現該問題,分別登入每個排程節點都無法復現,推測問題點可能出現在F5負載轉發方面。


2)F5裝置狀態及配置檢查


• F5運維人員反饋F5狀態正常,且配置和其餘三個叢集並無區別。結合現場情況瞭解到,其餘三個叢集透過F5地址登入均無法復現該問題。


3)系統配置檢查

(由於上述兩步均未發現問題,因此嘗試從系統環境配置方面排查一遍)


• 首先想到了操作上有不少網路相關配置,可以先對比一下正常環境和出現問題的環境引數配置。     


透過sysctl -a 將每個環境中的配置讀取並寫到檔案中,然後使用 diff 工具比對差異。


透過對比發現,可疑引數net.ipv4.tcp_tw_recycle,連線有問題的環境該引數配置為1,查詢相關資料分析該引數的影響。



4)初步定位問題


• 透過查閱資料發現 net.ipv4.tcp_tw_recycle引數在特定場景下確實會引起類似問題,因此我們先針對這個引數展開測試和驗證。


• 資料顯示,net.ipv4.tcp_tw_recycle引數和net.ipv4.tcp_timestamps引數配合使用。在使用NAT轉發的網路環境中,由於多個裝置之間不能保證時間完全同步,如果開啟了net.ipv4.tcp_tw_recycle,會檢查對端IP的時間戳是否遞增,如果不是遞增則會丟失網路包。


• 之後,登入伺服器檢視TCP資料情況,發現有大量的TCP SYN包被丟棄,並且數量一直在增長。



```powershell
$ netstat -s | grep -i listen
1825 times the listen queue of a socket overflowed
2751213 SYNs to LISTEN sockets dropped
```



5)修改配置,驗證問題是否解決


• 在視窗時間修改net.ipv4.tcp_tw_recycle為0


• 使用指令碼測試持續使用F5地址登入叢集,發現該問題不再復現。



## 2.3原因分析

1.為什麼會丟包?


time_wait出現在主動關閉tcp連線的一端(可能是服務端,也可能是客戶端,以下簡稱“本端”,對應的另外一段稱為“對端”),如果本端開啟了tcp_tw_recycle,觸發per-host PAWS機制,會檢查對端IP維度的timestamps是否遞增;如果不是遞增,會直接丟棄包(現象例如:傳送SYN包或資料包,對方沒有回包,這邊卻一直在重試,直到多次重試都失敗了,連線就會超時異常);


2.什麼環境下會丟包?


一般情況下,這種超時問題只會出現在對端是NAT的環境,如F5、LVS等負載均衡方案都使用了NAT技術。在本端看來,是同一個對端NAT IP連線過來的,而對端NAT環境下的多個裝置時間肯定會存在差異,因此一旦在本端開啟了net.ipv4.tcp_tw_recycle=1,對端傳送過來的攜帶timestamps的包就很難全部遞增(無論是對端NAT環境下哪個裝置傳送的包,都會被認為是對端NAT IP的包),本端就會丟棄timestamps不遞增的包,此時可能就會導致對端部分裝置收不到回包,多次重傳均失敗,連線就會出現異常。


3.如何避免該問題導致的丟包?


大多數情況下,tcp連線上的客戶端會主動發起fin關閉,則time_wait狀態會出現在客戶端而非服務端。這種情況下,服務端不需要考慮最佳化回收time_wait。但現在,大多數應用部署在伺服器上,它即會作為服務端對外提供服務,也會作為客戶端去請求其他伺服器上介面,前者是因為作為服務端,很少出現time_wait狀態;後者是因為作為客戶端很容易在伺服器上產生大量TCP time_wait狀態。因此,我們想快速回收time_wait,主要是針對後者的情況。


此時,如果我們想解決後者time_wait過多情況,在伺服器(注意是伺服器,不是服務端)上開啟tcp_tw_recycle快速回收埠,因為這臺伺服器上的應用同時又是作為服務端對外提供服務,tcp_tw_recycle觸發的pre-host PAWS機制則會使客戶端超時異常,因此,net.ipv4.tcp_tw_recycle=1不能輕易開啟。



## 本期覆盤總結



1)本次部署過程中,只關注了對資料庫影響較大的系統引數,忽視了一些常規引數;


2)現場基礎環境複雜多樣,部署前要做好基線檢查;


3)基線檢查要儘可能融合到自動化工具裡,實現標準化、規範化。



## 番外篇-展昭答疑解惑



1)怎麼規避tcp_tw_recycle帶來的問題呢?


答:首先,要明確自己的環境是否適合開啟此引數,比如用到NAT 網路地址轉換的場景下,儘量避免開啟tcp_tw_recycle引數;

另外,Linux 從核心4.12版本開始移除了tcp_tw_recycle 引數。因此,用大於4.12核心版本的小夥伴就不用擔心這個問題啦;

最後,生產環境的核心升級總是存在滯後性。因此,線上作業系統核心版本仍會存在大量4.12之前的核心版本,在環境部署時仍要稍加註意這個引數。


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/69997641/viewspace-3006101/,如需轉載,請註明出處,否則將追究法律責任。

相關文章