限流和降級(上) | 如何打造平臺穩定效能力(一)

許此一生發表於2018-08-28

在整個穩定性體系中,所包含的範圍非常廣泛,從機房的佈線、網路通訊、硬體部署、應用架構、資料容災等方面都與之相關。從共享服務中臺的角度看,則更多的是從應用架構設計和中介軟體平臺的維度對平臺的穩定性實現更精確化的管理和保障。本期開始,我們將從這個角度介紹阿里巴巴中介軟體團隊多年來為了提升平臺穩定性所做出的一系列技術創新和成果,包括限流和降級、流量排程、業務開關、容量壓測和評估、全鏈路壓測平臺業務一直性平臺等。

第一期:限流和降級

由於第一期的內容篇幅較多,我們將切分為上下兩個篇章。

一、限流和降級的產生背景

先設想一個場景,你開發了一個企業中非常核心的一個服務,日常情況下會有上百個應用呼叫,如果對服務的呼叫不加限制的使用,可能會因為某個應用開發的bug 或不合理的設計給服務造成非常大的壓力,直接導致所有服務節點全部被請求佔滿,使得原本非常核心的應用因為訪問服務超時而產生了很大的生成事故。從現象來說,所有服務節點看起來執行很繁忙,但從應用方的角度來看,因為服務響應時間過長,實際上該服務並沒有提供有效服務。從設定上來說,服務就是給其他應用提供服務的,使用者怎麼呼叫服務很難控制,所以必須從服務自身做好保護,否則可能因為一個小的問題造成平臺級的故障。

另一個是活動大促的場景,準備好的50臺機器資源可以應對預估的100萬參與人數,但實際情況是瞬間來了1000萬使用者,遠遠超過服務處理能力的訪問請求,會使後端的伺服器直接滿負荷運算,並伴隨著大量的資源搶佔和上下文切換,使平臺處理能力下降到一個極低的程度,影響業務請求的響應時間。類似的還有因為一個社會熱點,應用端出現使用者請求陡增的情況。

二、限流的作用和前期準備

限流的作用相當於電路上的保險絲,當過載的時候掐掉一點流量,讓系統有能力集中資源以較快的深度處理 平臺處理能力範圍內 的業務請求。也就是讓上面提到的大促場景中,僅讓1000萬使用者中的100萬使用者進入後端的處理流程中,將其餘900萬使用者的請求透過佇列或直接阻擋在平臺處理單元之外的方式,保障平臺在處理能力範圍內對100萬的使用者請求進行處理。

平臺要具備限流能力,需要配備好壓測和監控能力。

透過壓測,我們可以知道服務例項的部署最大能滿足多少的業務請求。但傳統的壓力測試方法都是採用模擬的資料,從實踐的角度來看,這些壓測資料與在實際生產環境中所表現的指標還是有比較大的偏差,也就是說,採用模擬資料進行壓力測試的方式並不能準確測量出平臺的能力峰值。阿里巴巴中介軟體團隊經過內部5年+的全生態沉澱,開發出的針對分散式場景,可模擬海量使用者的真實業務場景的效能測試產品PTS,能更方便和準確的對服務的容量進行評估,這在“如何打造系統穩定平臺”之後的章節中會詳細介紹。

在掌握服務的容量後,接下來就是針對服務資源的使用情況進行監控,透過資源監控的指標與之前所獲取的服務能力進行比較,如果超過服務處理上限則啟動限流。透過CPU、記憶體和磁碟IO等資源的使用情況來判斷系統目前的負載往往是不準確的。因為很多情況下系統本身的處理能力出於什麼樣的水位跟這些作業系統資源的使用情況沒有一個清晰的對應關係,所以在實際生產中,都會透過服務的QPS作為限流的關鍵判斷指標。

三、阿里巴巴是如何做限流管控的

對於平臺限流的實現,先從一個典型服務化應用架構的角度來看。使用者的請求首先會透過前端接入層(一般採用Nginx),分發到後端的應用叢集上,應用叢集中主要負責使用者的前端互動以及業務需求對後端服務叢集中的服務進行服務呼叫。為了避免出現遠超過系統處理負載上限的訪問請求,同時又能很好的兼顧安全問題,透過一些安全策略防止對平臺的惡意攻擊,所以最優的限流攔截點在前端接入層面,因為一旦讓“洪流”進入到系統的下層,對於系統的衝擊以及限流的難度都會加大。

阿里巴巴是透過在 Nginx 上實現的擴充套件元件 TMD(taobao missile defense淘寶導彈防禦系統)實現了接入層限流的主要工作,TMD系統可透過域名類限流、cookie限流、黑名單以及一些安全策略等很好的實現了在接入層的限流措施。

TMD系統包含了淘寶技術團隊開發的開源模組 nginx-http-sysguard,主要用於當訪問負載和記憶體達到一定的閾值時,會執行相應的動作,比如直接返回503、504或者其他url請求返回程式碼,一直等到記憶體或者負載回到閾值的範圍內,站點才恢復可用。

在模組 nginx-http-sysguard基礎上,淘寶TMD系統給使用者提供了視覺化的配置管理介面,方便使用者針對不同的業務場景實現不同的限流規則。如果來自單臺機器持續訪問淘寶平臺上的一個URL頁面,可在TMD中設定規則:訪問頻率大雨180次/秒,則進行IP訪問頻率限速或cookie訪問頻率限速。正是有了TMD 這樣配置靈活、操作方便的規則配置介面,運維人員可以針對所發現的異常請求以及實時的處理狀態,設定出各種保護措施,保障平臺在面對大流量時具備一定的自我保護能力,在平臺接入層外部驚濤駭浪的訪問洪流下,平臺接入蹭內部保持穩定、健康的執行狀態。

在接入層實現了限流後,一定會有部分使用者的請求得不到系統正常的處理,所以平臺一般會給使用者返回限流頁面,在一定程度上減少使用者因為請求沒有成功處理的失落體驗,限流頁面的風格會與網站、app的設計風格統一,頁面也會包含跳轉引導介面,以形成使用者體驗和業務處理流程的閉環。

四、TMD平臺在服務層面臨的挑戰

TMD平臺能很好的實現在平臺接入層的限流功能,但對於服務層就無能為力了。對於實現服務的限流控制,傳統的實現方式通常用spring的aop機制,對需要限流的介面定義一個advice攔截器,示例程式碼如下:

<bean id="spuServiceAdvisor"  class="org.springframework.aop.suppport.RegexpMethodPointcutAdvisor"><property name="partners">
    <list>
        <value>com.taobao.item.service.SpuService.*</value>
    </list>
    </property>
    <propetry name="advise">
        <ref bean="spuServiceApiAdvice" />
    </property></bean><bean id="spuServiceApiAdvice" />
    class="com.taobao.trade.buy.web.buy.util.monitor.advice.SpuServiceApiAdvice" />

其中的 SuperServiceApiAdvice 類實現MethodBeforeAdvice介面,重寫before方法,那麼在呼叫指定的介面或者方法前會計算當前thread count或qps,如果當前的執行緒數大於所設定的最大執行緒數閾值,則返回訪問限流的異常資訊。示例程式碼如下:

@Overrideprotected void invokeBeforeMethodForFlowControl(MonitorStore monitorStore) throws FlowControlException{long newThreadCnt = monitorStore
.getStoreDataInfo(getMonitorNmae(),getKey()).getThreadCnt()
.get();if(newThreadCnt > MonitorParam.MAX_THREAD_COUT_FIVE){   throw new FlowControlException(   "SpuServiceApiAdvice access control, threadcnt="
           + newThreadCnt);
    }
}

這套流控技術方案是可行的,實現起來也非常簡單,但在實際應用場景中還是會發現不少問題,比如:

  • 如果一個應用需要對100個介面進行限流,那麼對應地也就需要配置100個advice和編寫100個攔截器,如果是成百上千的應用呢?

  • 限流閥值是硬編碼形式,無法動態調整,當然你也可以動態調整(比如定義成一個靜態變數,然後透過curl去調整),但當限流開關達到一定量級後你會發現這是一件非常痛苦的事,很難維護管理;

  • 限流手段太過單一,無法對特殊場景實現多樣化的限流;

  • 沒有一個統一的監控平臺,無法監控當前的限流情況;

  • 限流演算法簡單,當在雙十一這種特殊場景,會看到毛刺現象,需要一種更平滑的限流演算法;


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31551794/viewspace-2213001/,如需轉載,請註明出處,否則將追究法律責任。

相關文章