<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          HttpClient 設(shè)置不當(dāng)引發(fā)的一次雪崩!

          共 3534字,需瀏覽 8分鐘

           ·

          2021-08-03 22:49

          上一篇:深夜看了張一鳴的微博,讓我越想越后怕

          一. 事件背景

          我最近運(yùn)維了一個(gè)網(wǎng)上的實(shí)時(shí)接口服務(wù),最近經(jīng)常出現(xiàn)Address already in use (Bind failed)的問題。

          很明顯是一個(gè)端口綁定沖突的問題,于是大概排查了一下當(dāng)前系統(tǒng)的網(wǎng)絡(luò)連接情況和端口使用情況,發(fā)現(xiàn)是有大量time_wait的連接一直占用著端口沒釋放,導(dǎo)致端口被占滿(最高的時(shí)候6w+個(gè)),因此HttpClient建立連接的時(shí)候會(huì)出現(xiàn)申請(qǐng)端口沖突的情況。

          具體情況如下:

          time_wait特征

          于是為了解決time_wait的問題,網(wǎng)上搜索了些許資料加上自己的思考,于是認(rèn)為可以通過連接池來保存tcp連接,減少HttpClient在并發(fā)情況下隨機(jī)打開的端口數(shù)量,復(fù)用原來有效的連接。但是新的問題也由連接池的設(shè)置引入了。

          二. 問題過程

          在估算連接池最大連接數(shù)的時(shí)候,參考了業(yè)務(wù)高峰期時(shí)的請(qǐng)求量為1分鐘1.2w pv,接口平響為1.3s(復(fù)雜的廣告推廣效果模擬系統(tǒng),在這種場(chǎng)景平響高是業(yè)務(wù)所需的原因)。

          因此qps為12000*1.3\60=260

          然后通過觀察了業(yè)務(wù)日志,每次連接建立耗時(shí)1.1s左右, 再留70%+的上浮空間(怕連接數(shù)設(shè)置小出系統(tǒng)故障),最大連接數(shù)估計(jì)為2601.1*1.7約等于500。

          為了減少對(duì)之前業(yè)務(wù)代碼最小的改動(dòng),保證優(yōu)化的快速上線驗(yàn)證,仍然使用的是HttpClient3.1 的MultiThreadedHttpConnectionManager,然后在線下手寫了多線程的測(cè)試用例,測(cè)試了下并發(fā)度確實(shí)能比沒用線程池的時(shí)候更高,然后先在我們的南京機(jī)房小流量上線驗(yàn)證效果,效果也符合預(yù)期之后,就開始整個(gè)北京機(jī)房的轉(zhuǎn)全。結(jié)果轉(zhuǎn)全之后就出現(xiàn)了意料之外的系統(tǒng)異常。。。

          三. 案情回顧

          在當(dāng)天晚上流量轉(zhuǎn)全之后,一起情況符合預(yù)期,但是到了第二天早上就看到用戶群和相關(guān)的運(yùn)維群里有一些人在反饋實(shí)況頁(yè)面打不開了。這個(gè)時(shí)候我在路上,讓值班人幫忙先看了下大概的情況,定位到了耗時(shí)最高的部分正是通過連接池調(diào)用后端服務(wù)的部分,于是可以把這個(gè)突發(fā)問題的排查思路大致定在圍繞線程池的故障來考慮了。

          于是等我到了公司,首先觀察了一下應(yīng)用整體的情況:

          四. 深入排查

          由于發(fā)現(xiàn)了有近 1/3的實(shí)例進(jìn)程崩潰,而業(yè)務(wù)流量沒變,由于RPC服務(wù)對(duì)provider的流量進(jìn)行負(fù)載均衡,所以引發(fā)單臺(tái)機(jī)器的流量升高,這樣會(huì)導(dǎo)致后面的存活實(shí)例更容易出現(xiàn)崩潰問題,于是高優(yōu)看了進(jìn)程掛死的原因。

          由于很可能是修改了HttpClient連接方式為連接池引發(fā)的問題,最容易引起變化的肯定是線程和CPU狀態(tài),于是立即排查了線程數(shù)和CPU的狀態(tài)是否正常

          1、CPU狀態(tài)

          CPU特征

          如圖可見Java進(jìn)程占用cpu非常高,是平時(shí)的近10倍

          2、線程數(shù)監(jiān)控狀態(tài):

          圖中可以看到多個(gè)機(jī)器大概在10點(diǎn)初時(shí),出現(xiàn)了線程數(shù)大量飆升,甚至超出了虛擬化平臺(tái)對(duì)容器的2000線程數(shù)限制(平臺(tái)為了避免機(jī)器上的部分容器線程數(shù)過高,導(dǎo)致機(jī)器整體夯死而設(shè)置的熔斷保護(hù)),因此實(shí)例是被虛擬化平臺(tái)kill了。之前為什么之前在南京機(jī)房小流量上線的時(shí)候沒出現(xiàn)線程數(shù)超限的問題,應(yīng)該和南京機(jī)房流量較少,只有北京機(jī)房流量的1/3有關(guān)。

          接下來就是分析線程數(shù)為啥會(huì)快速積累直至超限了。這個(gè)時(shí)候我就在考慮是否是連接池設(shè)置的最大連接數(shù)有問題,限制了系統(tǒng)連接線程的并發(fā)度。為了更好的排查問題,我回滾了線上一部分的實(shí)例,于是觀察了下線上實(shí)例的 tcp連接情況和回滾之后的連接情況

          回滾之前tcp連接情況:

          回滾之后tcp連接情況:

          發(fā)現(xiàn)連接線程的并發(fā)度果然小很多了,這個(gè)時(shí)候要再確認(rèn)一下是否是連接池設(shè)置導(dǎo)致的原因,于是將沒回滾的機(jī)器進(jìn)行jstack了,對(duì)Java進(jìn)程中分配的子線程進(jìn)行了分析,總于可以確認(rèn)問題。

          jstack狀態(tài):

          從jstack的日志中可以很容易分析出來,有大量的線程在等待獲取連接池里的連接而進(jìn)行排隊(duì),因此導(dǎo)致了線程堆積,因此平響上升。由于線程堆積越多,系統(tǒng)資源占用越厲害,接口平響也會(huì)因此升高,更加劇了線程的堆積,因此很容易出現(xiàn)惡性循環(huán)而導(dǎo)致線程數(shù)超限。

          那么為什么會(huì)出現(xiàn)并發(fā)度設(shè)置過小呢?之前已經(jīng)留了70%的上浮空間來估算并發(fā)度,這里面必定有蹊蹺!另外,Java 面試題和答案全部整理好了,微信搜索互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)發(fā)送:2T,可以在線閱讀。

          于是我對(duì)源碼進(jìn)行了解讀分析,發(fā)現(xiàn)了端倪:

          如MultiThreadedHttpConnectionManager源碼可見,連接池在分配連接時(shí)調(diào)用的doGetConnection方法時(shí),對(duì)能否獲得連接,不僅會(huì)對(duì)我設(shè)置的參數(shù)maxTotalConnections進(jìn)行是否超限校驗(yàn),還會(huì)對(duì)maxHostConnections進(jìn)行是否超限的校驗(yàn)。

          于是我立刻網(wǎng)上搜索了下maxHostConnections的含義:每個(gè)host路由的默認(rèn)最大連接,需要通過setDefaultMaxConnectionsPerHost來設(shè)置,否則默認(rèn)值是2。

          所以并不是我對(duì)業(yè)務(wù)的最大連接數(shù)計(jì)算失誤,而是因?yàn)椴恢酪O(shè)置DefaultMaxConnectionsPerHost而導(dǎo)致每個(gè)請(qǐng)求的Host并發(fā)連接數(shù)只有2,限制了線程獲取連接的并發(fā)度(所以難怪剛才觀察tcp并發(fā)度的時(shí)候發(fā)現(xiàn)只有2個(gè)連接建立 ?? )

          五. 案情總結(jié)

          到此這次雪崩事件的根本問題已徹底定位,讓我們?cè)俅尉珶挼目偨Y(jié)一下這個(gè)案件的全過程:

          1. 連接池設(shè)置錯(cuò)參數(shù),導(dǎo)致最大連接數(shù)為2
          2. 大量請(qǐng)求線程需要等待連接池釋放連接,出現(xiàn)排隊(duì)堆積
          3. 夯住的線程變多,接口平響升高,占用了更多的系統(tǒng)資源,會(huì)加劇接口的耗時(shí)增加和線程堆積
          4. 最后直至線程超限,實(shí)例被虛擬化平臺(tái)kill
          5. 部分實(shí)例掛死,導(dǎo)致流量轉(zhuǎn)移到其他存活實(shí)例。其他實(shí)例流量壓力變大,容易引發(fā)雪崩

          關(guān)于優(yōu)化方案與如何避免此類問題再次發(fā)生,我想到的方案有3個(gè):

          1. 在做技術(shù)升級(jí)前,要仔細(xì)熟讀相關(guān)的官方技術(shù)文檔,最好不要遺漏任何細(xì)節(jié)
          2. 可以在網(wǎng)上找其他可靠的開源項(xiàng)目,看看別人的優(yōu)秀的項(xiàng)目是怎么使用的。比如github上就可以搜索技術(shù)關(guān)鍵字,找到同樣使用了這個(gè)技術(shù)的開源項(xiàng)目。要注意挑選質(zhì)量高的項(xiàng)目進(jìn)行參考
          3. 先在線下壓測(cè),用控制變量法對(duì)比各類設(shè)置的不同情況,這樣把所有問題在線下提前暴露了,再上線心里就有底了
          以下是我設(shè)計(jì)的一個(gè)壓測(cè)方案:

          a. 測(cè)試不用連接池和使用連接池時(shí),分析整體能承受的qps峰值和線程數(shù)變化

          b. 對(duì)比setDefaultMaxConnectionsPerHost設(shè)置和不設(shè)置時(shí),分析整體能承受的qps峰值和線程數(shù)變化

          c. 對(duì)比調(diào)整setMaxTotalConnections,setDefaultMaxConnectionsPerHost 的閾值,分析整體能承受的qps峰值和線程數(shù)變化

          d. 重點(diǎn)關(guān)注壓測(cè)時(shí)實(shí)例的線程數(shù),cpu利用率,tcp連接數(shù),端口使用情況,內(nèi)存使用率

          綜上所述,一次連接池參數(shù)導(dǎo)致的雪崩問題已經(jīng)從分析到定位已全部解決。在技術(shù)改造時(shí)我們應(yīng)該要謹(jǐn)慎對(duì)待升級(jí)的技術(shù)點(diǎn)。

          在出現(xiàn)問題后,要重點(diǎn)分析問題的特征和規(guī)律,找到共性去揪出根本原因。

          原文鏈接:https://blog.csdn.net/qq_16681169/article/details/94592472


          感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。

              · END ·
          最后,關(guān)注公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)回復(fù):2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全。


          正文結(jié)束


          推薦閱讀 ↓↓↓

          1.不認(rèn)命,從10年流水線工人,到谷歌上班的程序媛,一位湖南妹子的勵(lì)志故事

          2.如何才能成為優(yōu)秀的架構(gòu)師?

          3.從零開始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧

          4.程序員一般可以從什么平臺(tái)接私活?

          5.37歲程序員被裁,120天沒找到工作,無奈去小公司,結(jié)果懵了...

          6.IntelliJ IDEA 2019.3 首個(gè)最新訪問版本發(fā)布,新特性搶先看

          7.這封“領(lǐng)導(dǎo)痛批95后下屬”的郵件,句句扎心!

          8.15張圖看懂瞎忙和高效的區(qū)別!

          一個(gè)人學(xué)習(xí)、工作很迷茫?


          點(diǎn)擊「閱讀原文」加入我們的小圈子!

          瀏覽 35
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天伊人久久 | 亚洲第一男人天堂 | 欧美一级操逼 | 久久久久夜色精 | 撸一撸操一操 |