歡迎關注我的微信公衆號:石杉的架構筆記(id:shishan100)java
每週一到週五早八點半!精品技術文章準時送上!!程序員
往期文章
1. 拜託!面試請不要再問我Spring Cloud底層原理
2. 【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?
目錄面試
1、寫在前面redis
2、場景引入,問題初現數據庫
3、揚湯止沸,飲鴆止渴緩存
4、問題爆發,洪水猛獸服務器
5、追本溯源,治標治本微信
6、總結全文,回眸再看網絡
相信很多朋友都在本身公司使用Spring Cloud框架來構建微服務架構,畢竟如今這是很是火的一門技術。架構
若是隻是用戶量不多的傳統IT系統,使用Spring Cloud可能還暴露不出什麼問題。
若是是較多用戶量,高峯每秒高達上萬併發請求的互聯網公司的系統,使用Spring Cloud技術就有一些問題須要注意了。
先不空聊原理、理論,來說一個真實的例子,這是個人一個朋友在創業互聯網公司發生過的真實案例。
朋友A的公司作互聯網類的創業,組建了一個小型研發團隊,上來就用了Spring Cloud技術棧來構建微服務架構的系統。一段時間沒日沒夜的加班,好不容易核心業務系統給作出來了,平時正常QA測試沒發現什麼大毛病,感受性能還不錯,一切都很完美。
而後系統就這麼上線了,一開始用戶規模很小,註冊用戶量小几十萬,日活幾千用戶。
天天都有新的數據進入數據庫的表中,就這麼日積月累的,沒想到數據規模竟然慢慢吞吞增加到了單表幾百萬。
這個時候呢,看起來也沒太大的毛病,就是有用戶反映,系統有些操做,會感受卡頓幾秒鐘,會刷不出來頁面。
這是爲啥呢?
若是你們對微服務框架有點了解的話,應該知道,好比Feign + Ribbon組成的服務調用框架,是有接口調用超時這一說的,有一些參數能夠設置接口調用的超時時間。
若是你調用一個接口,好幾秒刷不出來,人家就超時異常返回,用戶就刷不出來頁面了。
通常碰到這種事情,一大坨屎同樣的SQL擺在那兒,寫SQL的人過一個月本身都看不懂了,80%的工程師看着都不肯意去花時間重寫和優化。
一是修改的人力成本過高,二是誰敢負擔這責任呢?系統跑的好好的,就是慢了點而已,結果你硬是亂改一通,重構,把系統核心業務流程搞掛了怎麼辦?
因此說,那些兄弟第一反應是:增長超時時間啊!接口慢點能夠,可是別超時不響應啊!
讓接口執行個幾秒把結果返回,用戶不就能夠刷出來頁面了!不用重構系統了啊!輕鬆+愉快!
如何增長呢?很簡單,看下面的參數就知道了:
你們若是看過以前的文章,應該知道,Spring Cloud裏通常會用hystrix的線程池來執行接口調用的請求。
若是忘了這一點的,能夠回頭看看《拜託,面試請不要再問我Spring Cloud底層原理!》。
因此設置超時通常設置兩個地方,feign和ribbon那塊的超時,還有hystrix那塊的超時。其中後者那塊的超時通常必須大於前者。
Spring Cloud玩兒的好的兄弟,可千萬別看着這些配置發笑,由於我確實見過很多Spring Cloud玩兒的沒那麼溜的哥們,真的就這麼幹了。
好了,日子在繼續。。。
優化了參數後,看上去效果不錯,用戶雖然以爲有的頁面慢是慢點,可是起碼過幾秒能刷出來。
這個時候,日活幾千的用戶量,壓根兒沒什麼併發可言,高峯期每秒最多一二十併發請求罷了。
你們看看下面這張圖,感覺一下現場氛圍:
隨着時間的推移,公司業務高速發展……
那位兄弟的公司,在系統打磨成熟,幾萬用戶試點都ok以後,老闆立馬拿到一輪幾千萬的融資。
公司上上下下意氣風發啊!緊接着就是組建運營團隊,地推團隊,全國大範圍的推廣。
總之就是三個字:推!推!推!
這一推不打緊!研發人員在後臺系統發現,本身的用戶量蹭蹭蹭的增加,註冊用戶增加了幾十倍,突破了千萬級別,日活用戶也翻了幾十倍,在活動之類的高峯期,竟然達到了上百萬的日活用戶量。。。
幸福的煩惱。。。
爲何這麼說?由於用戶量上來後,悲劇的事情就發生了。
高峯期每秒的併發請求竟然達到了近萬的程度,研發團隊的兄弟們哪裏敢怠慢!在這個過程當中,先是緊張的各類擴容服務,一臺變兩臺,兩臺變八臺。
而後數據庫主從架構掛上去,讀寫分離是必須的,不然單個數據庫服務器哪能承載那麼大的請求!多搞幾個從庫,扛一下大量的讀請求,這樣基本就扛住了。
正準備鬆口氣,更加悲劇的事情就發生了。
在這個過程當中,那些兄弟常常會發現高峯期,系統的某個功能頁面,忽然就整個hang死了,就是無法再響應任何請求!全部用戶刷新這個頁面所有都是沒法響應!
這是爲何呢?
緣由很簡單啊!一個服務A的實例裏,專門調用服務B的那個線程池裏的線程,總共可能就幾十個。每一個線程調用服務B都會卡住5秒鐘。
那若是每秒鐘過來幾百個請求這個服務實例呢?一會兒那個線程池裏的線程就所有hang死了,無法再響應任何請求了。
你們來看看下面這張圖,再直觀的感覺一下這個無助的過程!
這個時候咋辦?兄弟們只能祭出程序員最古老的法寶,重啓機器!
遇到頁面刷不出來,只能重啓機器,至關於短暫的初始化了一下機器內的資源。
而後接着運行一段時間,又卡死,再次重啓!真是使人崩潰啊!用戶們的體驗是極差的,老闆的心情是憤怒的!
畫外音:
其實這個問題自己不大,但若是對Spring Cloud沒有高併發場景的真實經驗,確實可能會跟這幫兄弟同樣,搞出些莫名其妙的問題。
好比這個公司,明明應該去優化服務接口性能,結果硬是調大了超時時間。結果致使併發量高了,對那個服務的調用直接hang死,系統的核心頁面刷不出來,影響用戶體驗了,這怪誰呢?
無法子了,那幫兄弟們只能找人求助。下面就是做者全程指導他們完成系統優化的過程。
第一步
關鍵點,優化圖中核心服務B的性能。互聯網公司,核心業務邏輯,面向C端用戶高併發的請求,不要用上百行的大SQL,多表關聯,那樣單表幾百萬行數據量的話,會致使一下執行好幾秒。
其實最佳的方式,就是對數據庫就執行簡單的單表查詢和更新,而後複雜的業務邏輯所有放在java系統中來執行,好比一些關聯,或者是計算之類的工做。
這一步幹完了以後,那個核心服務B的響應速度就已經優化成幾十毫秒了,是否是很開心?從幾秒變成了幾十毫秒!
第二步
那個超時的時間,也就是上面那段ribbon和hystrix的超時時間設置。
奉勸各位同窗,不要由於系統接口的性能過差而懶惰,搞成幾秒甚至幾十秒的超時,通常超時定義在1秒之內,是比較通用以及合理的。
爲何這麼說?
由於一個接口,理論的最佳響應速度應該在200ms之內,或者慢點的接口就幾百毫秒。
若是一個接口響應時間達到1秒+,建議考慮用緩存、索引、NoSQL等各類你能想到的技術手段,優化一下性能。
不然你要是胡亂設置超時時間是幾秒,甚至幾十秒,萬一下游服務偶然出了點問題響應時間長了點呢?那你這個線程池裏的線程立馬所有卡死!
具體hystrix的線程池以及超時時間的最佳生產實踐,請見下一篇文章:《微服務架構如何保障雙11狂歡下的99.99%高可用》
這兩步解決以後,其實系統表現就正常了,核心服務B響應速度很快速,並且超時時間也在1秒之內,不會出現hystrix線程池頻繁卡死的狀況了。
第三步
事兒還沒完,你要真以爲兩步就搞定了,那仍是經驗不足。
若是你要是超時時間設置成了1秒,若是就是由於偶然發生的網絡抖動,致使接口某次調用就是在1.5秒呢?這個是常常發生的,由於網絡的問題,接口調用偶然超時。
因此此時配合着超時時間,通常都會設置一個合理的重試,以下所示:
設置這段重試以後,Spring Cloud中的Feign + Ribbon的組合,在進行服務調用的時候,若是發現某臺機器超時請求失敗,會自動重試這臺機器,若是仍是不行會換另一臺機器重試。
這樣因爲偶爾的網絡請求形成的超時,不也能夠經過自動重試避免了?
第四步
其實事兒還沒完,若是把重試參數配置了,結果你竟然就放手了,那仍是沒對人家負責任啊!
你的系統架構中,只要涉及到了重試,那麼必須上接口的冪等性保障機制。
不然的話,試想一下,你要是對一個接口重試了好幾回,結果人家重複插入了多條數據,該怎麼辦呢?
其實冪等性保證自己並不複雜,根據業務來,常見的方案:
相似這樣的方案還有一些。總之,要保證一個接口被屢次調用的時候,不能插入重複的數據。
有圖有真相!老規矩,最後給你們上一張圖,最終優化後的系統表現大概是長下面這樣子的。
若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!
一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上,歡迎掃描下方二維碼,持續關注
《雙11背後每秒上萬併發下的Spring Cloud參數優化實戰》,敬請期待
《微服務架構如何保障雙11狂歡下的99.99%高可用》,敬請期待
歡迎關注我的微信號:石杉的架構筆記(id:shishan100)
週一至週五早八點半!精品技術文章準時送上
十餘年BAT架構經驗傾囊相授