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

歡迎訪問 生活随笔!

生活随笔

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

数据库

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

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

背景:

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

問題分析:

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

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

?

控制臺(tái)中的日志報(bào)錯(cuò)為以下截圖2:

圖2 控制臺(tái)日志報(bào)錯(cuò)圖標(biāo)題

?

起初我也認(rèn)為這是一個(gè)簡單的數(shù)據(jù)庫連接超時(shí)問題,于是首先進(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)啟動(dòng)的時(shí)候連接是沒有報(bào)錯(cuò)的,且前幾次連接都沒有問題,超時(shí)是出現(xiàn)在幾次正常連接后;

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

定位問題:

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

圖3 控制臺(tái)日志其他異常報(bào)錯(cuò)圖題

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

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

???????? 緊接著通過在數(shù)據(jù)庫虛機(jī)上進(jìn)行抓包,發(fā)現(xiàn)數(shù)據(jù)庫丟包嚴(yán)重。同時(shí)發(fā)現(xiàn)pod注冊在eureka上是pod的ip,而連接數(shù)據(jù)庫和redis以及mq的時(shí)候,就是通過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連接中為了端口快速回收,會(huì)對連接進(jìn)行時(shí)間戳的檢查,如果發(fā)現(xiàn)后續(xù)請求中時(shí)間戳小于緩存的時(shí)間戳,即視為無效,相應(yīng)數(shù)據(jù)包會(huì)被丟棄,這樣就造成了大量的丟包。

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

圖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í)間戳數(shù)據(jù)沒有變化。對于數(shù)據(jù)庫來說,請求的源地址是node節(jié)點(diǎn)IP,所以在數(shù)據(jù)庫看來,原先不同的客戶端請求經(jīng)過NAT的轉(zhuǎn)發(fā),會(huì)被認(rèn)為是同一個(gè)連接,加上不同客戶端的時(shí)間可能不一致,所以就會(huì)出現(xiàn)時(shí)間戳錯(cuò)亂的現(xiàn)象。這樣就會(huì)導(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)整),而我們忽視了這個(gè)日志的報(bào)錯(cuò),把它當(dāng)成了一個(gè)普通的工程連接超時(shí)問題看待。想要明白問題出現(xiàn)的原因,首先需要明白TCP連接中TIME-WAIT狀態(tài),如下圖5所示:

?

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

?

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

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

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

    圖6 ACK包異常丟棄圖

    當(dāng)最后一個(gè)ACK丟失時(shí),遠(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)為這個(gè)連接是有效的,則會(huì)繼續(xù)與其通訊,導(dǎo)致這個(gè)連接會(huì)被重新打開。當(dāng)遠(yuǎn)程收到一個(gè)SYN 時(shí),會(huì)回復(fù)一個(gè)RST包,因?yàn)檫@SEQ不對,那么新的連接將無法建立成功,報(bào)錯(cuò)終止。如果遠(yuǎn)程因?yàn)樽詈笠粋€(gè)ACK包丟失,導(dǎo)致停留在LAST-ACK狀態(tài),將影響新建立具有相同四元組的TCP連接。

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

    ?

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

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

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

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

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

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

    最后,理解了TIME_WAIT狀態(tài)的原理就可以很好的解決這個(gè)問題了,最合適的解決方案是增加更多的四元組數(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有一種行為,可以緩存每個(gè)連接最新的時(shí)間戳,后續(xù)請求中如果時(shí)間戳小于緩存的時(shí)間戳,即視為無效,相應(yīng)的數(shù)據(jù)包會(huì)被丟棄。

    1.net.ipv4.tcp_tw_reuse

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

    2.net.ipv4. tcp_tw_recycle

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

    在Linux中是否啟用這個(gè)行為取決于tcp_timestampstcp_tw_recycle,因?yàn)?span style="color:#f33b45;">tcp_timestamps缺省就是開啟的,所以當(dāng)tcp_tw_recycle被開啟后,這種行為就被激活了。

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

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

    總結(jié):

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

    (本文已在公眾號發(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)容還不錯(cuò),歡迎將生活随笔推薦給好友。