www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]- 1 - 事件背景 我在鳳巢團隊獨立搭建和運維的一個高流量的推廣實況系統(tǒng),是通過HttpClient?調(diào)用大搜的實況服務(wù)。最近經(jīng)常出現(xiàn)Address already in use (Bind failed)的問題。 很明顯是一個端口綁定沖突的問題,于是大概排查了一下當(dāng)前系統(tǒng)的網(wǎng)絡(luò)連接情況和端


-

1

-


事件背景


我在鳳巢團隊獨立搭建和運維的一個高流量的推廣實況系統(tǒng),是通過HttpClient 調(diào)用大搜的實況服務(wù)。最近經(jīng)常出現(xiàn)Address already in use (Bind failed)的問題。


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


具體情況如下:


HttpClient 連接池設(shè)置引發(fā)的一次雪崩!


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



-

2

-



問題過程



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


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

為了減少對之前業(yè)務(wù)代碼最小的改動,保證優(yōu)化的快速上線驗證,仍然使用的是HttpClient3.1 的MultiThreadedHttpConnectionManager,設(shè)置核心代碼如下:


public void init() {
        connectionManager = new MultiThreadedHttpConnectionManager();
        HttpConnectionManagerParams managerParams = new HttpConnectionManagerParams();
        managerParams.setMaxTotalConnections(500); // 最大連接數(shù)
        connectionManager.setParams(managerParams);
        client = new HttpClient(connectionManager);
    }



然后在線下手寫了多線程的測試用例,測試了下并發(fā)度確實能比沒用線程池的時候更高,然后先在我們的南京機房小流量上線驗證效果,效果也符合預(yù)期之后,就開始整個北京機房的轉(zhuǎn)全。結(jié)果轉(zhuǎn)全之后就出現(xiàn)了意料之外的系統(tǒng)異常。。。



-

3

-



案情回顧



在當(dāng)天晚上流量轉(zhuǎn)全之后,一起情況符合預(yù)期,但是到了第二天早上就看到用戶群和相關(guān)的運維群里有一些人在反饋實況頁面打不開了。


這個時候我在路上,讓值班人幫忙先看了下大概的情況,定位到了耗時最高的部分正是通過連接池調(diào)用后端服務(wù)的部分,于是可以把這個突發(fā)問題的排查思路大致定在圍繞線程池的故障來考慮了。


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


  1. 監(jiān)控平臺的業(yè)務(wù)流量表現(xiàn)正常,但是部分機器的網(wǎng)卡流量略有突增

  2. 接口的平響出現(xiàn)了明顯的上升

  3. 業(yè)務(wù)日志無明顯的異常,不是底層服務(wù)超時的原因,因此平響的原因肯定不是業(yè)務(wù)本身

  4. 發(fā)現(xiàn)30個機器實例竟然有9個出現(xiàn)了掛死的現(xiàn)象,其中6個北京實例,3個南京實例


-

4

-



深入排查



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


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


CPU狀態(tài)


如圖可見Java進程占用cpu非常高,是平時的近10倍。


HttpClient 連接池設(shè)置引發(fā)的一次雪崩!


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


HttpClient 連接池設(shè)置引發(fā)的一次雪崩!

HttpClient 連接池設(shè)置引發(fā)的一次雪崩!


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


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


回滾之前tcp連接情況


HttpClient 連接池設(shè)置引發(fā)的一次雪崩!


回滾之后tcp連接情況


HttpClient 連接池設(shè)置引發(fā)的一次雪崩!


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


jstack狀態(tài)


HttpClient 連接池設(shè)置引發(fā)的一次雪崩!


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


那么為什么會出現(xiàn)并發(fā)度設(shè)置過小呢?之前已經(jīng)留了70%的上浮空間來估算并發(fā)度,這里面必定有蹊蹺!


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


HttpClient 連接池設(shè)置引發(fā)的一次雪崩!


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


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


所以并不是我對業(yè)務(wù)的最大連接數(shù)計算失誤,而是因為不知道要設(shè)置DefaultMaxConnectionsPerHost而導(dǎo)致每個請求的Host并發(fā)連接數(shù)只有2,限制了線程獲取連接的并發(fā)度(所以難怪剛才觀察tcp并發(fā)度的時候發(fā)現(xiàn)只有2個連接建立 )



-

5

-



案情總結(jié)



到此這次雪崩事件的根本問題已徹底定位,讓我們再次精煉的總結(jié)一下這個案件的全過程:


  • 連接池設(shè)置錯參數(shù),導(dǎo)致最大連接數(shù)為2

  • 大量請求線程需要等待連接池釋放連接,出現(xiàn)排隊堆積

  • 夯住的線程變多,接口平響升高,占用了更多的系統(tǒng)資源,會加劇接口的耗時增加和線程堆積

  • 最后直至線程超限,實例被虛擬化平臺kill

  • 部分實例掛死,導(dǎo)致流量轉(zhuǎn)移到其他存活實例。其他實例流量壓力變大,容易引發(fā)雪崩。


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


  • 在做技術(shù)升級前,要仔細(xì)熟讀相關(guān)的官方技術(shù)文檔,最好不要遺漏任何細(xì)節(jié)

  • 可以在網(wǎng)上找其他可靠的開源項目,看看別人的優(yōu)秀的項目是怎么使用的。比如github上就可以搜索技術(shù)關(guān)鍵字,找到同樣使用了這個技術(shù)的開源項目。要注意挑選質(zhì)量高的項目進行參考

  • 先在線下壓測,用控制變量法對比各類設(shè)置的不同情況,這樣把所有問題在線下提前暴露了,再上線心里就有底了



以下是我設(shè)計的一個壓測方案:


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

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

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

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


綜上所述,一次連接池參數(shù)導(dǎo)致的雪崩問題已經(jīng)從分析到定位已全部解決。在技術(shù)改造時我們應(yīng)該要謹(jǐn)慎對待升級的技術(shù)點。在出現(xiàn)問題后,要重點分析問題的特征和規(guī)律,找到共性去揪出根本原因。

End

作者:zxcodestudy ,本文版權(quán)歸作者所有

https://blog.csdn.net/qq_16681169/article/details/94592472

特別推薦一個分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:

HttpClient 連接池設(shè)置引發(fā)的一次雪崩!

HttpClient 連接池設(shè)置引發(fā)的一次雪崩!

HttpClient 連接池設(shè)置引發(fā)的一次雪崩!

長按訂閱更多精彩▼

HttpClient 連接池設(shè)置引發(fā)的一次雪崩!

如有收獲,點個在看,誠摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉
關(guān)閉