設置默認的超時和重試是一個基礎設施的基本素養


What

本篇應該是穩定性「三十六計」系列的一篇:超時重試。但是「設置默認的超時和重試是一個基礎設施的基本素養」這句話我在我們組內三次開會的時候都說了。表達了我的一個理念。

 

Why

為什么一個基礎設施要設置默認的超時和重試?想象下面一個場景。

TCP協議里有一些基本的概念:MSL、TTL、RTT。

MSL(Maximum Segment Lifetime)

報文最大生存時間,它是任何報文在網絡上存在的最長時間。超時報文就被丟棄。

TTL(Time To Live)

生存時間,是由源主機設置初始值,經常存的是ip數據包可以經過的最大路由數,每經過一個處理路由數減1,當值為0則報文被丟棄。

RTT(Round-trip time)

客戶端到服務器往返所花時間。

 

嗯?不是很明白?這就對了。想象這些東西都沒有默認值,需要我們自己去設置,是不是很頭大?

作為基礎設施,自己應該是做過數據統計的、做過壓測的。自己的性能是什么樣的,怎么使用更為合理,基礎設施的開發團隊最為清楚,不應該將這種設置的責任交給調用方或者客戶端來做,加大對基礎設施的學習成本。

 

再來討論一個問題:為什么要超時和重試?

長尾問題

 

如上圖,隨便找了一個調用的耗時。從上面可以看到平均耗時13.9ms,百分之99的耗時在30ms內,最大耗時有488ms。那對於超過100ms的請求來說,是不是在30ms內還不返回就直接丟棄這個請求重新發起一個,新請求有99%的概率在30ms內返回結果,從時間上更划算?

而之所以對同一個請求性能差距很大,原因很多,常見的有服務過載和隊列過長。

死鎖問題

想象一個分布式鎖,沒有超時時間。萬一釋放鎖時失敗了,其他人永遠不能獲取這個鎖。而如果有超時時間,鎖過期后,其他的請求通過重試是可以獲取到鎖的。

 

How

怎么設置超時和重試。guava-trying是個不錯的java實現。其實不管什么語言都不是難事,難的是超時和重試條件是什么,設置多少合理。

超時和重試條件根據業務不同有差異。

一般的超時條件可設置為TP95(95%的請求)的2倍。或者智能一點,根據大數據統計一下,用個機器學習算法看看怎么設置總體耗時最小。

重試的一個比較好的實踐是每次重試的時間間隔成指數級增長,並且根據集群情況設置合理上限。這樣就避免本來服務已經過載了,短時間內大量重試造成多米諾骨牌效應(雪崩)。

合理的上限相當重要,因為有些請求不應該再重試了。比如服務器過載時限流策略收到請求不會將請求交給執行層而是直接返回一個響應。而如果客戶端判斷:“我去,這么快就給我結果啦!太好了,下個請求繼續給力哦~~”這種錯誤的正反饋循壞可能會成為資源耗盡的最后一根稻草。

 

相關閱讀

編寫代碼的「八榮八恥」(上篇)

編寫代碼的「八榮八恥」- 以開關上線為榮,以自信編碼為恥

穩定性「三十六計」- 配額管控

「前任的50種死法」開發踩坑案例--慢就是錯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM