狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

日常問題排查-空閑一段時間再請求就超時

freeflydom
2025年5月7日 8:54 本文熱度 128

問題現場

問題是喜聞樂見的調用超時。這個問題的顯著特征是:

1.流量小的時候容易出現偶發性訪問超時,一般是空閑很長時間后的第一筆請求超時。
2.調大超時時間沒有任何效果,平常請求在1s內就能返回。但出現這類超時的時候就算調整到1min超時時間依舊會超時。
3.超時后的重試調用一般都會成功。
4.同一時間其它相同調用不會出現問題。
5.在內網調用不會出現這個問題,在非內網調用不管是專線還是互聯網都容易出現這個問題。
6.服務端無法搜索到任何日志,仿佛這個超時請求沒有出現過。

猜想1:服務端關閉了連接

一個非常直觀的猜想就是服務端關閉了這個鏈接,請求直接被拒絕了。但熟悉tcp協議的筆者很快否定了這個猜想,如果連接被關閉了,會有下面圖中所示的兩種情況:

serverclientserverclientalt[client未收到FIN包][client收到FIN包]請求正常返回close連接tcp packettcp resetsocket has already closed

第一種情況,client端沒有收到服務端返回的FIN包,那么在請求發送后應該是直接被對端Reset,立刻感知到報錯。

第二種情況,client端收到了服務端返回的FIN包,那么在請求發送前會直接報socket has already closed,立刻感知到報錯。

根據上面的判斷,無論什么情況都是立刻返回,而不是等待很長時間之后超時,和特征2不符,于是可以否定由于服務端關閉連接導致。

猜想2:偶發性路由翻動

因為過了非常長的時間才超時,這時候,我們的就可以考慮是在網絡層丟包了。那么到底為什么丟包呢?難道是偶發性的路由翻動?這個想法立馬被筆者否決了。因為,如果是路由翻動一般會在分鐘級別的收斂,而我們觀察到在5s超時后的重試都是成功的。而且一旦路由翻動這段時間內所有的請求都應該收到影響,而問題現場其它請求確實正常的。這就和特征3/特征4不符合。

猜想3(真正的原因)

其實這個問題筆者一直遇到,而且解決方案也一直有,但從沒有真正的仔細思考過。但最近讀《tcpip路由技術》卷二突然靈光一閃,將書中的一些闡述和這個問題莫名的關聯想通了其中的關竅。人們由于IPv4地址即將耗盡而不得不開發出NAT技術,而NAT畢竟只是個補丁,其無法完整的融合進TCP導致出現種種因為這個補丁而出現的問題。我們通過NAT設備中的轉發表項維護內網的ip:port和外網的ip:port之間的映射,入下圖所示:

很明顯的,由于client和server的數量是非常多的(因為多個服務可能公用一個公網IP),所以轉發表是一個非常寶貴的資源,一旦轉發表滿了,就無法創建新的連接路徑了。所以,一些長期沒有流量需要有一個定時的清理機制騰出轉發表以供新的連接創建。如下圖所示,在tcp連接estalbish狀態后一定時間內沒有任何流量,NAT會直接清空這個轉發表項,而client和server端無法感知到這一點,于是client端只好在多次NAT重傳后超時。這個和Bug現場的各種特征完全一致。當然無論是NAT-1和NAT-2都有可能清理轉發表,只要有一個過期那么這個連接就會出現超時。

使用LVS做NAT的默認超時時間

那么我們看一下我們最常用的使用LVS做NAT的默認超時時間是多少,讓我們來番一下LVS源代碼:

static const int tcp_timeouts[IP_VS_TCP_S_LAST+1] = {
	[IP_VS_TCP_S_NONE]		=	2*HZ,
	[IP_VS_TCP_S_ESTABLISHED]	=	15*60*HZ, // 這邊設定了ESTABLISHED狀態的超時時間為15min
	[IP_VS_TCP_S_SYN_SENT]		=	2*60*HZ,
	[IP_VS_TCP_S_SYN_RECV]		=	1*60*HZ,
	[IP_VS_TCP_S_FIN_WAIT]		=	2*60*HZ,
	[IP_VS_TCP_S_TIME_WAIT]		=	2*60*HZ,
	[IP_VS_TCP_S_CLOSE]		=	10*HZ,
	[IP_VS_TCP_S_CLOSE_WAIT]	=	60*HZ,
	[IP_VS_TCP_S_LAST_ACK]		=	30*HZ,
	[IP_VS_TCP_S_LISTEN]		=	2*60*HZ,
	[IP_VS_TCP_S_SYNACK]		=	120*HZ,
	[IP_VS_TCP_S_LAST]		=	2*HZ,
};
struct ip_vs_conn *ip_vs_conn_new(......)
{
	......
	timer_setup(&cp->timer, ip_vs_conn_expire, 0); // 在初始化連接的時候設置超時函數ip_vs_conn_expire
	......
}
static void ip_vs_conn_expire(struct timer_list *t){
	......
	if (likely(ip_vs_conn_unlink(cp))) { // 在這里清理轉發表
	......
	}
	......
}
static inline void set_tcp_state(......) 
{
	......
	// 通過狀態在tcp_timeout表中找到相應的超時時間并設置進timeout
	cp->timeout = pd->timeout_table[cp->state = new_state];
	......
}

從上面代碼中我們可以看到,LVS通過設置的timeout_table來設置轉發表項超時時間,而不同的tcp狀態會有不同的超時時間,而默認的established的超時時間是15 * 60 * HZ也就是15min。也就是說,在默認不設置的情況下,15min中之后這個連接就會GG。

解決方案

好了,了解完原理之后,我們就可以有解決方案了。第一種方案,就是使用短連接。也就是每次請求的時候新建一個連接,NAT本身對tcp的FIN包做了處理,一旦發生四次揮手會自動清理表項。用完即回收,即減少了NAT設備轉發表的壓力也不會產生過一段時間超時的問題。但這個方案有個缺陷,也是短連接的固有缺陷。由于復用不了連接,短時候有海量的請求過來產生大量的短連接,由于TCP 2MSL機制的存在,client即有可能出現端口耗盡。而端口耗盡后會導致Kernel在搜索可用端口號的時候性能急劇劣化(每次搜索端口從數次循環急劇劣化到每次搜多端口都要數萬次循環),這會導致client端的機器CPU利用率急劇上升,一直陷在搜索端口號的循環里面導致整體不可用! 如下圖所示:

具體分析可以見筆者的另一篇博客: https://my.oschina.net/alchemystar/blog/4436558

為了解決第一種的方案的問題,我們可以依舊復用連接,只不過這個復用時間特別短,例如6s之內復用,超過6s的連接就直接丟棄。這樣既能在大量請求涌過來的時候扛住,又能解決長時間不用的超時問題。HttpClient其實提供這個機制,如下所示:

HttpClients.custom().evictIdleConnections(6, TimeUnit.SECONDS)

第三種方案,我們可以輪詢每一個connection發送心跳包,但這個實現起來比較麻煩,遠沒有上面的HttpClient內置方案省心。

還有一個需要提到的是Http的Keep-alive,連接的保持時間是在Server端設置的。而這個Keep-alive timeout可能 > NAT的清理時間。對于Client端來說很難約束Server端的配置。所以筆者還是建議采用第二種方案。

總結

NAT雖然大幅度延長了IPV4地址耗盡的時間,但由于只是打了補丁,它的固有缺陷會導致很多問題。不過我們會根據遇到問題的原因給出各種解決的方案,從而讓系統穩定的運行。如果具備相應的基礎知識,這個問題非常容易解決。但如果沒有對整個通信過程有一個大致的理解,會無從著手,所以系統化的學習非常重要。

轉自https://www.cnblogs.com/alchemystar/p/18860539


該文章在 2025/5/7 8:54:29 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved