服務器過載保護

服務器過載保護(上篇)——過載介紹 http://wetest.qq.com/lab/view/?id=69 前端


何爲過載web

過載一詞,在海量服務的後臺開發中,基本都會遇到。何爲過載,即當前負載已經超過了系統的最大處理能力。例如,系統每秒可以處理的請求是100個,但實際每秒的請求量倒是1000個,就能夠斷定系統出現了過載。算法

過載的定義看似簡單,但倒是處理過載問題的關鍵。對於任何其餘問題,一樣得抓住問題的本質,方可不偏離問題核心,萬變而不離其宗。後端

過載後果

過載的出現,會致使部分服務不可用,若是處置不當,極有可能引發服務徹底不可用,乃至雪崩。安全

咱們的系統中,因爲是單線程狀態機的處理模式,順序處理全部連接的緩衝區消息,當出現處理能力的降低或者請求量大幅增長,致使處理能力小於請求量的狀況下,消息就會在系統緩衝區中堆積,形成消息處理的延遲會持續增長,在正式環境中,連接數目較多,系統緩衝區較大,最終會致使消息處理延遲大到不可接受的程度,最終會致使處理的都是無效消息,形成服務不可用。服務器

固然具體的業務須要具體的分析,把握住問題的影響,纔可以作到一切盡在掌握,根據墨菲定律,一般對後果的判斷不該過於樂觀,謹慎行事、考慮充分纔可以作到成竹在胸。網絡

過載緣由

過載的出現,不一樣系統模型的具體緣由都會有所不一樣,例如CPU跑滿,頻繁讀寫致使IO瓶頸,內存耗盡,請求量突增等等。但究其根本緣由,能夠歸結爲兩點:多線程

1、處理能力的降低;負載均衡

2、請求量的上升。框架

只有對自身系統的有更深層和透徹的瞭解,才能更好地考慮如何處置問題。頭疼醫頭,腳疼醫腳的處理問題方式,只能解決一時之需,對症下藥,纔是解決問題的根本之道。

任何問題的保護行爲能夠依據事件發生的階段分爲:

一、 發生前,預防;

二、 發生時,處置;

三、 發生後,恢復。

但在保護的措施中,都和業務的模型有着相關性,沒有徹底統一的方案,適合本身的纔是最好的。

過載預防

在過載發生前的預防,就需在系統設計之初,依據具體的業務模型能夠考慮預防過載的措施:

一、 優化服務處理流程,下降處理資源消耗,提高自身處理能力;例如CPU消耗型服務,是否能夠考慮優化算法,提高處理能力。

二、 分離處理模塊;將負載分擔到不一樣的模塊或者服務器;例如IO是瓶頸的服務,考慮是否能夠將IO模塊進行分離。

三、 負載均衡;將請求量分流,下降單服請求量。

四、 輕重模塊分離;重要模塊單獨部署和處理,防止模塊之間的互相影響。

五、 前端防護;在前端控制請求頻率,緩解後端壓力;例如客戶端能夠作保護措施,控制聊天頻率,點擊操做失敗,能夠延時一段時間,才容許用戶繼續點擊;前端服務發現後端出現過載問題,可選擇性拒絕服務,下降後端壓力。

六、 使用緩衝區;緩衝區的使用,能夠幫咱們抵擋請求量的抖動,但緩衝區的使用一樣也有不少技巧,並不是越大越好。首先須要考慮內存,cpu等資源的開銷,業務的模型是否須要這麼大的緩衝區。例如緩衝區過大,處理完整個緩衝區,都須要幾十秒,而前端等待超時則爲幾秒,那麼每次處理緩衝區的內容,都是舊的,前端認爲都是超時,服務徹底不可用。另外是後端卻又處理成功,會致使系統信息不對稱,從而致使更爲嚴重的問題,例如,在遊戲中購買道具的場景,前端扣用戶的錢,認爲超時失敗而不給用戶發對應的物品,後端卻又執行成功了,嚴重運營問題就此產生。

七、 作好監控,及時告警;例如當CPU達到80%時,當處理請求超出必定閾值時,及時告警,作好擴容,優化等其餘準備。

固然依據業務模型的不一樣,還有不少預防的措施,依然是前述作到知底,纔可以找出適合自身的方法。

過載保護

處理過載的方法有許多,適用於不一樣的業務場景,並沒有絕對的最優方案,合適的纔是最好的,但能匹配上合適一詞,是對系統總體和經驗的一個考驗。下面介紹一些經常使用的處理方案以及咱們是如何作的:

Ø 請求量閾值控制

在系統部署上線以前,預估好系統的處理能力,限定最大同時可以處理的請求量、流量或者連接數。當請求量快接近於最大處理能力時,則告警,超過範圍,則觸發拒絕請求機制。因而可知對於閾值的設置是一個很關鍵的環節,閾值太高,依然可能致使過載,閾值太低,則又致使負載上不去。閾值的設置也會是一個不斷調優的過程。該方法的優勢和缺陷都很明顯。

優勢:識別和處理簡單;

缺點:閾值的設定須要必定的經驗,會有必定的難度,同時若是處理能力發生變化時,閾值就很難動態發生變化。

Ø 監控系統資源

服務器監控CPU,內存等資源的使用狀況,設定閾值,超出閾值,則能夠認爲過載,從而觸發拒絕請求機制。

優勢:使用動態的資源數據,從相對根本的緣由上識別過載,而無需過多關心具體的業務處理;

缺點:一是處理相對複雜;二是在某些場景下,資源數據的耗盡並不意味着出現過載的狀況。例如服務開了較大的內存池,看起來內存資源耗盡了,實際上負載是足夠的,又如如今都是多核服務器跑着多進程或者多線程的服務,單一的CPU耗盡也不可以表明服務就出現過載,但又可能產生過載,這就和具體業務有關;三是在某些場景下,出現過載的狀況,也不必定會耗盡資源,例如當前全部的服務都在等待之中(多是後端的回覆或者其餘),一樣也不會對CPU、內存、io、網絡等資源形成影響,但依然進入了過載。整體來講該方式適合的場景相對會簡單點。

Ø 檢測請求到達時間

依據請求處理的時延來判斷是否過載。記錄請求到達的時間戳,和處理請求結束的時間戳,獲得請求到達自身服務器處理的時延,超出閾值,則可斷定爲超時失效,能夠直接丟棄。使用獨立模塊讀取系統緩衝區中數據,打上時間戳,存入消息緩衝區,在處理時,超過必定時延的請求,則拒絕處理,由於能夠認爲即便處理了也是無用的。從中能夠看出時間戳很關鍵(爲啥會單獨提出這個問題,由於在後續的方案設計中,時間戳依然是解決過載問題的關鍵點,此處先賣個關子)。

A、 時間戳若是使用本地讀取時刻調用系統的時間函數獲取,就沒有考慮消息包到達系統緩衝區的時間,所以是萬萬不能這樣作。

B、 到能夠經過ioctl調用SIOCGSTAMP的接口,得到時間戳,但這會加大系統開銷,緣由是每次recv完,都須要從新設置一下ioctl一次。而且不是線程安全的。

C、 使用socket選項SO_TIMESTAMP,經過帶外數據獲取到數據到達系統緩衝區的時間。

其處理方式以下圖所示:

 

經過這種方式已經可以很好地解決負載問題,經過如此,並不須要設置過於繁瑣的配置或者去識別過載的問題,目前此方法在SPP的框架中在使用。我的以爲可能存在的一些問題在於:

一、 徹底使用時間戳過時的方式來判斷,並不必定適合全部場景,假設處理耗時過長,而在緩衝區中也呆了較長時間,但請求量並不大,服務器未過載,在處理一些須要強寫入的狀況下,單靠該機制也會稍許欠妥。但若是加入一些協議上層機制,告訴該消息務必執行,也是可避免的。

二、 在出現過載的狀況之下,極可能會致使總體的服務都會產生一個固定的延時,由於每次拋棄到可執行的範圍內,至少會有一個超時時間範圍內的延時,若是是較長的服務鏈的話,最前面的等待服務極可能會出現超時,所以其延時的設置相對也很困難,太小就太過靈敏,過大就會出現剛所述的問題。

 

三、 該方式只是管理了到達本服務器緩衝區以後的問題,並無考慮整條服務鏈上的延時,極可能到達本服務器緩衝區時,就已通過期了,而且有可能這些數據在對端緩衝區已經產生了堆積,但到本端,並不會判斷其過時。

四、 剩下還有一些內容能夠作更多優化:另外SO_TIMESTAMP使用的是系統時間,會受系統時間修改的影響,但這個問題也不大,由於即便修改了,影響的只是本次系統緩衝區的數據。其餘能夠考慮業務的輕重程度,作按服務來丟棄。


服務器過載保護(下篇)——過載處理新方案 http://wetest.qq.com/lab/view/?id=70

相關文章
相關標籤/搜索