1.概述
最近看了一篇關於熱key導致redis服務叢集掛掉的文章, 非常的精彩導致我在想當流量非常大時為什麼redis服務會掛掉,於是我就找了大量的資料研究服務為什麼會掛掉及其原理,伺服器為什麼會當機等等就有了如下內容。
其實服務崩潰總結起來無非就兩種,一種是資源枯竭導致的服務崩潰,另一種就是超時引起的服務崩潰。
2.資源枯竭導致
先說第一種資源枯竭導致的服務崩潰,顧名思義就是因為伺服器的資源或者分配的資源不能滿足服務執行的需要從而引發服務崩潰。比較常見有記憶體溢位,磁碟滿載,頻寬不足等三種。
寫java的程式設計師遇到最多的估計就是記憶體溢位了,比如作業系統給jvm分配了2G的實體記憶體供程式執行使用,可能有個程式頭鐵在一段程式碼中建立了迴圈引用的物件或者大量未能及時回收的物件,在請求量大時gc不能及時回收垃圾物件導致堆記憶體一直在增大超過了作業系統所分配的2G記憶體,此時就會觸發作業系統的kill -9訊號把程式殺死這樣使用者再請求服務時就無響應了。
電商大促期間前有很多準備工作,其中有一項就是去運營商那裡購買寬頻,這是因為在大促期間有大量使用者訪問,如果機器頻寬不足會導致服務崩潰,進而導致非常大損失。我們以一臺機器80M的寬頻為例,經過計算能承受的最大下載速度就是10M/s, 拿單個使用者的一個請求資料大小為10k為例,在1s內有1024個使用者請求時需要80M的寬頻機器剛好能滿足要求,如果是1s內有2000使用者請求時需要160M的流量那麼處理完這2000個使用者的請求需要2s,如果持續30s都有2000個使用者來請求服務,那麼就需要4800M的流量處理完需要600多s那麼就會大量請求出現等待進而引發超時導致服務崩潰。
3.超時導致
第二種超時引起的服務崩潰,就是大量使用者請求服務時因為大面積連線超時導致服務崩潰,和寬頻不足的例子很像,我們以單臺機器服務啟動單程式為例,在一個程式中我們通常會通過執行緒池去處理請求,我們假設執行緒池中一共有1000個請求來處理請求且每個請求的響應時間為100ms,當1s鐘有10000個請求發來時我們可以很快的處理並返回,當1s內有20000個請求發來時伺服器要處理就需要2s鐘的時間了,那麼在一段持續時間20000請求來時就會積壓大量的請求不能被處理導致超時,然後後面過來的請求肯定超時,這樣服務就崩潰了。
4.總結
在真實的生產環境,崩潰的原因可能會非常複雜且是多種因素互相作用的結果,但瞭解了服務奔潰的本質後就能很快找到對應的解決方案,如萬能的增加機器,優化程式碼邏輯,加入快取等等。完畢!