記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

問題描述:公司有個不常用的系統提供給外部客戶使用,隔三岔五會接到有客戶反映頁面刷不出來的問題。
臨時解決:重啓應用進程立馬生效,或等待一段時間後即可正常訪問。

先來了解下系統部署方式:
1)這個系統使用的應用連接的是我們備用數據庫;
2)備用數據庫目前只給這個系統的應用使用。

下面進行兩組簡單的測試:
1)本地PLSQL連接,過一段時間後會斷掉。(排除應用側問題)
2)將應用配置成訪問主用數據庫,問題現象消失(排除應用側問題+1)

好了,排除了應用側的問題,那麼問題就集中在了數據庫側,通過與網絡工程師溝通,備用數據庫獨立用了一臺硬件防火牆,其他都是共用的,和主庫無差異。

問題基本就定位到這了:
1)備用數據庫上層防火牆問題(網絡工程師排查,防火牆配置與主庫一致)
2)備用數據庫問題(數據庫工程師排查,數據庫配置與主庫一致)

好了,大家都說沒問題,那我們就只能通過分析拿數據說話了。
-----------------------------------------------------

進入正式測試階段:
1)斷開應用外部流量,重啓應用,應用和DB服務器都建立了連接。
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

2)過幾小時後,應用的連接還在,DB服務器的連接都沒有。

記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

what?DB服務器你憑什麼斷我應用連接啊?你斷我也不告訴我嗎?!!!
通過抓包發現,DB服務器當時是發送了keepalived檢測消息,但是應用你沒有收到啊。(DB大寫的冤枉~~)
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

嘿,防火牆你出來,我(應用)爲什麼沒有收到?

3)此時,通過訪問請求頁面已打不開,一直在請求中,通過在應用側抓包發現,應用有發送請求給DB,DB卻也沒有收到。(DB你可以出來,也罵一頓應用了,哈哈)
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

啦啦啦:這個時候,一切的定位都指向了防火牆,等把防火牆挪掉就知道了,問題到這裏基本就定位結束了。

PS:其實後來又做了一次測試,就是連接建立後過30分鐘,應用和DB兩側連接都是正常的,但是前端請求就訪問不了了,即DB還沒觸發keepalived機制,應用就觸發了TCP重傳機制,所以更可以說明問題不在應用和DB兩側了。


加餐話題

想知道DB是過了多久斷開的嗎?應用又是連了多少次才重新建立連接的嗎?他們的檢測機制又是什麼樣的呢?

加餐開始:
1、DB端的斷開機制。
DB作爲服務端,當2小時內都沒有收到客戶端(應用)的請求,就會觸發操作系統的keepalived機制。

具體如下:
net.ipv4.tcp_keepalive_time = 7200 #2小時後,開始發起ack檢測
net.ipv4.tcp_keepalive_probes = 9 #一共進行9次檢測
net.ipv4.tcp_keepalive_intvl = 75 #每次檢測間隔75秒

抓包示例:
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

發起的keepalived檢測一共發起了9次,每次75秒,一共花費了10分鐘,當都沒有收到響應,就會發起RST結束當前連接。
也就是說,應用和DB建立的連接,在沒有外部請求的情況下,通過DB和應用之前通訊斷開的情況下,DB會在2小時10分鐘後斷開連接。

2、應用端的重連機制。
當外部沒有請求的情況下,應用作爲客戶端,之前建立的連接始終“保持着”。
當外部發起請求時,會觸發TCP重連機制。

具體如下:
Linux重傳機制:
最小重傳時間是200ms
最大重傳時間是120s
重傳次數爲15

不信你看:
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)
中間省略。。。
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

timer:(on,9.794ms,15) 具體含義分別是:TCP重傳機制開啓,重傳倒計時,重傳次數。
抓包示例:
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

再來看看最後一次的重傳時間:
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

可以看出,在重傳第15次後,還需要再等2分鐘後,確定沒收到纔要關閉,即10:31:58 第16次是自我關閉連接(不再發送消息)。

通過命令分析出來的和LINUX自身的TCP重傳機制(圖片來自網上)其實是一樣的:
記一次應用訪問數據庫超時的問題分析(涉及linux的keepalived機制和TCP重傳機制)

可以看出,一個連接的TCP重傳機制需要花費15.4分鐘,才能重新創建連接。

所以,到這裏,就可以解釋爲什麼上面說的,當客戶反應訪問不了,過一段時間後就又可以訪問的現象了。
這裏應用和DB保持着10個連接,當DB側全部超時後,第一個請求過來,會選擇其中一個空閒的連接,觸發了TCP重傳機制,需要等待15.4分鐘。一個客戶訪問頁面可能會觸發N個請求,那麼就會等待15.4*N分鐘。
即用戶可以打開頁面的時間需要等待15.4分鐘~154分鐘。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章