天天看點

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

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

第一期:限流和降級

由于第一期的内容篇幅較多,我們将切分為上下兩個篇章。

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

先設想一個場景,你開發了一個企業中非常核心的一個服務,日常情況下會有上百個應用調用,如果對服務的調用不加限制的使用,可能會因為某個應用開發的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,如果目前的線程數大于所設定的最大線程數門檻值,則傳回通路限流的異常資訊。示例代碼如下:

@Override
protected 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去調整),但當限流開關達到一定量級後你會發現這是一件非常痛苦的事,很難維護管理;
  • 限流手段太過單一,無法對特殊場景實作多樣化的限流;
  • 沒有一個統一的監控平台,無法監控目前的限流情況;
  • 限流算法簡單,當在雙十一這種特殊場景,會看到毛刺現象,需要一種更平滑的限流算法;

那麼我們是如何解決以上的問題?解決的過程中有哪些新的思考?阿裡巴巴是否有将這類解決方案開源貢獻給社群?我們将在下一篇“如何打造平台穩定性能力”系列文章中為大家解讀。

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