性能設計技術之淺談過載保護

發表于:2012-05-11來源:騰訊大講堂作者:不詳點擊數: 標簽:軟件測試
過載保護,看似簡單,但是要做好并不容易。這里用兩個曾經經歷的反面案例,給出過載保護的直觀展現,并附上一點感想。 案例一基本情況 如下圖,進程A是一個單進程系統,通過udp套接字接收前端請求進行處理。在處理過程中,需要訪問后端系統B,

  過載保護,看似簡單,但是要做好并不容易。這里用兩個曾經經歷的反面案例,給出過載保護的直觀展現,并附上一點感想。

  案例一基本情況

  如下圖,進程A是一個單進程系統,通過udp套接字接收前端請求進行處理。在處理過程中,需要訪問后端系統B,是同步的方式訪問后端系統B,根據后端系統B的SLA,超時時間設置是100ms。前端用戶請求的超時時間是1s。

  進程A的時序是:

  Step1: 從socket接收緩沖區接收用戶請求

  Step2: 進行本地邏輯處理

  Step3: 發送請求到后端系統B

  Step4: 等待后端系統B返回

  Step5: 接收后端系統B的應答

  Step6: 應答前端用戶,回到step1處理下一個請求

1.gif

 

  正常情況下的負載

  正常情況下:

  1、前端請求報文大小約100Bytes。前端請求的峰值每分鐘1800次,即峰值每秒30次。

  2、后端系統B并行能力較高,每秒可以處理10000次以上,絕大多數請求處理時延在20ms內。

  3、進程A在處理請求的時候,主要時延是在等待后端系統B,其他本地運算耗時非常少,小于1ms

  這個時候,我們可以看出,系統工作良好,因為處理時延在20ms內,每秒進程A每秒中可以處理50個請求,足以將用戶每秒峰值30個請求及時處理完。

  導火索

  某天,后端系統B進行了新特性發布,由于內部邏輯變復雜,導致每個請求處理時延從20ms延長至50ms,根據sla的100ms超時時間,這個時延仍然在正常范圍內。當用戶請求達到峰值時間點時,災難出現了,用戶每次操作都是“服務器超時無響應”,整個服務不可用。

  過載分析

  當后端系統B處理時延延長至50ms的時候,進程A每秒只能處理20個請求(1s / 50ms = 20 )。小于正常情況下的用戶請求峰值30次/s。這個時候操作失敗的用戶往往會重試,我們觀察到前端用戶請求增加了6倍以上,達到200次/s,是進程A最大處理能力(20次/s)的10倍!

  這個時候為什么所有用戶發現操作都是失敗的呢? 為什么不是1/10的用戶發現操作能成功呢? 因為請求量和處理能力之間巨大的差異使得5.6s內就迅速填滿了socket接收緩沖區(平均能緩存1000個請求,1000/(200-20)=5.6s),并且該緩沖區將一直保持滿的狀態。這意味著,一個請求被追加到緩沖區里后,要等待50s(緩存1000個請求,每秒處理20個,需要50s)后才能被進程A 取出來處理,這個時候用戶早就看到操作超時了。換句話說,進程A每次處理的請求,都已經是50s以前產生的,進程A一直在做無用功。雪球產生了。

  案例二基本情況

  前端系統C通過udp訪問后端serverD,后端server D的udp套接字緩沖區為4MB,每個請求大小約400字節。后端serverD偶爾處理超時情況下,前端系統C會重試,最多重試2次。

2.gif

 

  正常情況下的負載

  正常情況,后端serverD單機收到請求峰值為300次/s,后端serverD單機處理能力是每秒1500次,時延10ms左右。這個時候工作正常。

  導火索

  由于產品特性(例如提前通知大量用戶,未來某某時刻將進行一項秒殺活動;類似奧運門票,大量用戶提前得知信息:某日開始發售門票),大量的用戶聚集在同一時刻發起了大量請求,超出了后臺serverD的最大負載能力。操作響應失敗的用戶又重試, 中間系統的重試,進一步帶來了更大量的請求(正常情況下的9倍)。導致所有用戶操作都是失敗的。

  過載分析

  只是導火索不一樣,同案例一,巨大的請求和處理能力之間的鴻溝,導致后端serverD的4M大小的接收緩沖區迅速填滿(4秒就填滿),且過載時間內,接收緩沖區一直都是滿的。而處理完緩沖區內的請求,ServerD需要6秒以上(4MB / 400 / 1500 = 6.7S)。所以serverD處理的請求都是6s之前放入緩沖區的,而該請求在最前端早已經超時。雪球形成了。

  啟示

  1、 每個系統,自己的最大處理能力是多少要做到清清楚楚。例如案例一中的前端進程A,他的最大處理能力不是50次/s,也不是20次/S,而是10次/S。因為它是單進程同步的訪問后端B, 且訪問后端B的超時時間是100ms,所以他的處理能力就是1S/100ms=10次/S。而平時處理能力表現為50次/S,只是運氣好。

  2、 每個系統要做好自我保護,量力而為,而不是盡力而為。對于超出自己處理能力范圍的請求,要勇于拒絕。

  3、 每個系統要有能力發現哪些是有效的請求,哪些是無效的請求。上面兩個案例中,過載的系統都不具備這中慧眼,逮著請求做死的處理,雪球時其實是做無用功。

  4、 前端系統有保護后端系統的義務,sla中承諾多大的能力,就只給到后端多大的壓力。這就要求每一個前后端接口的地方,都有明確的負載約定,一環扣一環。

  5、 當過載發生時,該拒絕的請求(1、超出整個系統處理能力范圍的;2、已經超時的無效請求)越早拒絕越好。就像上海機場到市區的高速上,剛出機場就有電子公示牌顯示,進入市區某某路段擁堵,請繞行。

  6、 對于用戶的重試行為,要適當的延緩。例如登錄發現后端響應失敗,再重新展現登錄頁面前,可以適當延時幾秒鐘,并展現進度條等友好界面。當多次重試還失敗的情況下,要安撫用戶。

  7、 產品特性設計和發布上,要盡量避免某個時刻導致大量用戶集體觸發某些請求的設計。發布的時候注意灰度。

  8、 中間層server對后端發送請求,重試機制要慎用,一定要用的話要有嚴格頻率控制。

  9、 當雪球發生了,直接清空雪球隊列(例如重啟進程可以清空socket 緩沖區)可能是快速恢復的有效方法。

  10、過載保護很重要的一點,不是說要加強系統性能、容量,成功應答所有請求,而是保證在高壓下,系統的服務能力不要陡降到0,而是頑強的對外展現最大有效處理能力。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97