日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

记一次现网k8s中pod连接数据库异常的问题分析及解决实践(tcp_tw_recycle与tcp_tw_reuse内核参数修改)

發(fā)布時間:2023/12/31 数据库 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 记一次现网k8s中pod连接数据库异常的问题分析及解决实践(tcp_tw_recycle与tcp_tw_reuse内核参数修改) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

背景:

在某項目部署測試過程中, k8s中的微服務(wù)出現(xiàn)連接集群之外的數(shù)據(jù)庫服務(wù)超時,雖然是偶發(fā)性,但出現(xiàn)頻率較高,已對安全產(chǎn)品按期交付構(gòu)成較大風(fēng)險,需要盡快解決。

問題分析:

為方便更加清晰的理解問題,首先介紹下服務(wù)整體部署架構(gòu)。在3臺VM虛機(jī)中部署k8s集群,在k8s集群內(nèi)部署安全產(chǎn)品的容器服務(wù),而數(shù)據(jù)庫服務(wù)則是部署另外3臺VM進(jìn)行高可用,部署架構(gòu)圖1如下:

圖1 安全服務(wù)整體架構(gòu)圖標(biāo)題

?

控制臺中的日志報錯為以下截圖2:

圖2 控制臺日志報錯圖標(biāo)題

?

起初我也認(rèn)為這是一個簡單的數(shù)據(jù)庫連接超時問題,于是首先進(jìn)行了常規(guī)的排查。

1.檢查工程的k8s配置文件中db host的配置問題,沒有問題;

2.檢查網(wǎng)絡(luò)狀態(tài),進(jìn)入容器中對數(shù)據(jù)庫ip地址進(jìn)行telnet測試,也是可以正常返回的,沒有問題;

3.檢查數(shù)據(jù)庫主機(jī)是否有對源包進(jìn)行限制,運(yùn)維同事反饋并未對安全產(chǎn)品訪問做限制,沒有問題;

4.檢查HikariCP數(shù)據(jù)庫連接池配置,經(jīng)過日志排查,發(fā)現(xiàn)啟動的時候連接是沒有報錯的,且前幾次連接都沒有問題,超時是出現(xiàn)在幾次正常連接后;

5.檢查是否存在慢查詢和數(shù)據(jù)庫連接數(shù)是否正常,一切正常。

定位問題:

經(jīng)過多輪的檢查,并嘗試修改數(shù)據(jù)庫連接配置,發(fā)現(xiàn)無論對數(shù)據(jù)庫配置連接的參數(shù)如何修改,雖然數(shù)據(jù)庫連接日志報錯信息發(fā)生了變化,但是尋根究底,其本質(zhì)原因依舊是超時的問題,如下圖3。

圖3 控制臺日志其他異常報錯圖題

由于所有資源池都使用了相同的標(biāo)準(zhǔn)化k8s環(huán)境,導(dǎo)致排查問題時直接忽略了k8s本身,各種嘗試未果后我們將目光重新投向了k8s集群本身

???????? 確定是否是k8s集群的問題很簡單,將k8s上部署的服務(wù)進(jìn)行停止,不改變工程及配置,在虛機(jī)上采用java -jar的方式將服務(wù)啟動,對出問題的接口進(jìn)行高頻調(diào)用測試,沒有出現(xiàn)過一次數(shù)據(jù)庫連接超時問題。

???????? 緊接著通過在數(shù)據(jù)庫虛機(jī)上進(jìn)行抓包,發(fā)現(xiàn)數(shù)據(jù)庫丟包嚴(yán)重。同時發(fā)現(xiàn)pod注冊在eureka上是pod的ip,而連接數(shù)據(jù)庫和redis以及mq的時候,就是通過NAT轉(zhuǎn)換成node節(jié)點(diǎn)的ip了,那么問題極有可能就是出現(xiàn)在k8s的工程連接到數(shù)據(jù)庫虛機(jī)的網(wǎng)絡(luò)方式有問題

解決問題:

???????? 經(jīng)過定位發(fā)現(xiàn)是TCP的連接出現(xiàn)了問題。在TCP連接中為了端口快速回收,會對連接進(jìn)行時間戳的檢查,如果發(fā)現(xiàn)后續(xù)請求中時間戳小于緩存的時間戳,即視為無效,相應(yīng)數(shù)據(jù)包會被丟棄,這樣就造成了大量的丟包。

???????? 查看數(shù)據(jù)庫主機(jī)的內(nèi)核參數(shù),如下圖4,發(fā)現(xiàn)net.ipv4.tcp_tw_recyclenet.ipv4.tcp_timestamps參數(shù)同時設(shè)置為1了,因此將net.ipv4.tcp_tw_recycle設(shè)置為0關(guān)閉。原來當(dāng)開啟了tcp_tw_recycle選項后,會拒絕非遞增請求連接。當(dāng)連接進(jìn)入TIME_WAIT?狀態(tài)后,會記錄對應(yīng)遠(yuǎn)端主機(jī)最后到達(dá)節(jié)點(diǎn)的時間戳。如果同樣的主機(jī)有新的節(jié)點(diǎn)到達(dá),且時間戳小于之前記錄的時間戳,即視為無效,相應(yīng)的數(shù)據(jù)包會被丟棄。關(guān)閉這個設(shè)置后成功解決問題,再也沒有出現(xiàn)過超時問題。

圖4 虛機(jī)內(nèi)核參數(shù)配置圖

?

在k8s環(huán)境中,node節(jié)點(diǎn)上的pod網(wǎng)絡(luò)互聯(lián)互通是采用網(wǎng)絡(luò)插件結(jié)合etcd實(shí)現(xiàn)的。 默認(rèn)情況下pod訪問集群外部的網(wǎng)絡(luò)走的是對應(yīng)node節(jié)點(diǎn)的NAT規(guī)則。在這次連接中,由于在pod內(nèi)連接數(shù)據(jù)庫經(jīng)過了一次NAT轉(zhuǎn)換,客戶端TCP請求到達(dá)數(shù)據(jù)庫,修改目的地址(IP+端口號)后便轉(zhuǎn)發(fā)給數(shù)據(jù)庫服務(wù)器,而客戶端時間戳數(shù)據(jù)沒有變化。對于數(shù)據(jù)庫來說,請求的源地址是node節(jié)點(diǎn)IP,所以在數(shù)據(jù)庫看來,原先不同的客戶端請求經(jīng)過NAT的轉(zhuǎn)發(fā),會被認(rèn)為是同一個連接,加上不同客戶端的時間可能不一致,所以就會出現(xiàn)時間戳錯亂的現(xiàn)象。這樣就會導(dǎo)致后面的數(shù)據(jù)包被大量的丟棄,具體的表現(xiàn)就是客戶端發(fā)送的SYN,服務(wù)端遲遲無法響應(yīng)ACK。

原理分析:

???????? 問題最終通過修改了內(nèi)核參數(shù)net.ipv4.tcp_tw_recycle解決了,但是問題出現(xiàn)的原因以及問題的解決方案值得我們研究。

其實(shí)在文章的一開始的日志截圖中,實(shí)際上已經(jīng)可以看出端倪,對于Linux,字段為TCP_TIMEWAIT_LEN硬編碼為30秒,對于Windows為2分鐘(可自行調(diào)整),而我們忽視了這個日志的報錯,把它當(dāng)成了一個普通的工程連接超時問題看待。想要明白問題出現(xiàn)的原因,首先需要明白TCP連接中TIME-WAIT狀態(tài),如下圖5所示:

?

圖5 TCP狀態(tài)機(jī)圖

?

當(dāng)TCP連接關(guān)閉之前,首先發(fā)起關(guān)閉的一方會進(jìn)入TIME-WAIT狀態(tài),另一方可以快速回收連接。可以使用ss –tan來查看TCP連接的當(dāng)前狀態(tài)。

對于TIME-WAIT狀態(tài)來說,有兩個作用:

  • 確保遠(yuǎn)端(服務(wù)端)能夠正確的處于關(guān)閉狀態(tài),如圖:
  • ?

    圖6 ACK包異常丟棄圖

    當(dāng)最后一個ACK丟失時,遠(yuǎn)程連接進(jìn)入LAST-ACK狀態(tài),它可以確保遠(yuǎn)程已經(jīng)關(guān)閉當(dāng)前TCP連接。如果沒有TIME-WAIT狀態(tài),當(dāng)遠(yuǎn)程仍認(rèn)為這個連接是有效的,則會繼續(xù)與其通訊,導(dǎo)致這個連接會被重新打開。當(dāng)遠(yuǎn)程收到一個SYN 時,會回復(fù)一個RST包,因為這SEQ不對,那么新的連接將無法建立成功,報錯終止。如果遠(yuǎn)程因為最后一個ACK包丟失,導(dǎo)致停留在LAST-ACK狀態(tài),將影響新建立具有相同四元組的TCP連接。

    2.防止上一次連接中的包,又重新收到,影響新的連接,如圖7

    ?

    圖7 正常連接中,出現(xiàn)了SEQ3異常重新收到圖

    防止上一個TCP連接的延遲的數(shù)據(jù)包(發(fā)起關(guān)閉,但關(guān)閉沒完成),被接收后,影響到新的TCP連接。(唯一連接確認(rèn)方式為四元組:源IP地址、目的IP地址、源端口、目的端口),包的序列號也有一定作用,會減少問題發(fā)生的幾率,但無法完全避免。尤其是較大接收windows size的快速(回收)連接。

    ???????? 那大量堆積的TCP TIME_WAIT狀態(tài)在服務(wù)器上會造成什么影響呢?

  • 占用連接資源
  • TIME_WAIT占用的1分鐘時間內(nèi),相同四元組(源地址,源端口,目標(biāo)地址,目標(biāo)端口)的連接無法創(chuàng)建,通常一個ip可以開啟的端口為net.ipv4.ip_local_port_range指定的32768-61000,如果TIME_WAIT狀態(tài)過多,會導(dǎo)致無法創(chuàng)建新連接。

    2.占用內(nèi)存資源

    保持大量的連接時,當(dāng)多為每一連接多保留1分鐘,就會多消耗一些服務(wù)器的內(nèi)存。

    最后,理解了TIME_WAIT狀態(tài)的原理就可以很好的解決這個問題了,最合適的解決方案是增加更多的四元組數(shù)目,比如,服務(wù)器可用端口,或服務(wù)器IP,讓服務(wù)器能容納足夠多的TIME-WAIT狀態(tài)連接。

    在常見的互聯(lián)網(wǎng)架構(gòu)中(NGINX反代跟NGINX,NGINX跟FPM,FPM跟redis、mysql、memcache等),減少TIME-WAIT狀態(tài)的TCP連接,最有效的是使用長連接,不要用短連接,尤其是負(fù)載均衡跟web服務(wù)器之間。在服務(wù)端,不要啟用net.ipv4.tcp_tw_recycle,除非你能確保你的服務(wù)器網(wǎng)絡(luò)環(huán)境不是NAT。在服務(wù)端上啟用net.ipv4.tw_reuse對于連接進(jìn)來的TCP連接來說,是沒有任何效果的

    拓展:

    關(guān)于內(nèi)核參數(shù)的詳細(xì)介紹可以參考官方文檔。這邊簡單說明下tcp_tw_recycle參數(shù),在RFC1323中有這么一段描述:

    An additional mechanism could be added to the TCP, a per-host?cache of the last timestamp received from any connection.?This value could then be used in the?PAWS?mechanism to reject?old duplicate segments from earlier incarnations of the?connection, if the timestamp clock can be guaranteed to have?ticked at least once since the old connection was open. This?would require that the TIME-WAIT delay plus the RTT together?must be at least one tick of the sender’s timestamp clock.?Such an extension is not part of the proposal of this RFC.

    其大致意思就是TCP有一種行為,可以緩存每個連接最新的時間戳,后續(xù)請求中如果時間戳小于緩存的時間戳,即視為無效,相應(yīng)的數(shù)據(jù)包會被丟棄。

    1.net.ipv4.tcp_tw_reuse

    RFC 1323?實(shí)現(xiàn)了TCP拓展規(guī)范,以保證網(wǎng)絡(luò)繁忙狀態(tài)下的高可用。除此之外,另外,它定義了一個新的TCP選項–兩個四字節(jié)的timestamp fields時間戳字段,第一個是TCP發(fā)送方的當(dāng)前時鐘時間戳,而第二個是從遠(yuǎn)程主機(jī)接收到的最新時間戳。啟用net.ipv4.tcp_tw_reuse后,如果新的時間戳,比以前存儲的時間戳更大,那么linux將會從TIME-WAIT狀態(tài)的存活連接中,選取一個,重新分配給新的連接出去的TCP連接

    2.net.ipv4. tcp_tw_recycle

    這種機(jī)制也依賴時間戳選項,這也會影響到所有進(jìn)來和出去的連接。Linux將會放棄所有來自遠(yuǎn)程端的Timestamp時間戳小于上次記錄的時間戳(也是遠(yuǎn)程端發(fā)來的)的任何數(shù)據(jù)包。除非TIME-WAIT狀態(tài)已經(jīng)過期。當(dāng)遠(yuǎn)程端主機(jī)HOST處于NAT網(wǎng)絡(luò)中時,時間戳在一分鐘之內(nèi)(MSL時間間隔)將禁止了NAT網(wǎng)絡(luò)后面,除了這臺主機(jī)以外的其他任何主機(jī)連接,因為他們都有各自CPU CLOCK,各自的時間戳。

    在Linux中是否啟用這個行為取決于tcp_timestampstcp_tw_recycle,因為tcp_timestamps缺省就是開啟的,所以當(dāng)tcp_tw_recycle被開啟后,這種行為就被激活了。

    簡單來說就是,Linux會丟棄所有來自遠(yuǎn)端的timestamp時間戳小于上次記錄的時間戳(由同一個遠(yuǎn)端發(fā)送的)的任何數(shù)據(jù)包。也就是說要使用該選項,則必須保證數(shù)據(jù)包的時間戳是單調(diào)遞增的。同時從4.10內(nèi)核開始,官方修改了時間戳的生成機(jī)制,所以導(dǎo)致?tcp_tw_recycle 和新時間戳機(jī)制工作在一起不那么友好,同時?tcp_tw_recycle 幫助也不那么的大。此處的時間戳并不是我們通常意義上面的絕對時間,而是一個相對時間。很多情況下,我們是沒法保證時間戳單調(diào)遞增的

    tcp_tw_recycle 選項在4.10內(nèi)核之前還只是不適用于NAT/LB的情況(其他情況下,也非常不推薦開啟該選項),但4.10內(nèi)核后徹底沒有了用武之地,并且在4.12內(nèi)核中被移除。

    總結(jié):

    總體來說,這次數(shù)據(jù)庫連接超時故障本身并沒什么高深之處,不過拔出蘿卜帶出泥,在過程中牽扯的方方面面還是值得我們一起研究學(xué)習(xí)的,因此分享出這篇文章,也幫助遇到此類問題的小伙伴提供一個解決問題的思考方向。

    (本文已在公眾號發(fā)布,轉(zhuǎn)載請注明出處。)

    參考文檔:

    https://tools.ietf.org/html/rfc1323

    https://www.jianshu.com/p/25e99b2d1956

    https://blog.csdn.net/chengm8/article/details/51668992

    總結(jié)

    以上是生活随笔為你收集整理的记一次现网k8s中pod连接数据库异常的问题分析及解决实践(tcp_tw_recycle与tcp_tw_reuse内核参数修改)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。