流量監控實戰

      前言
     流量監控(後面簡稱流控)是一個比較大的領域,也是互聯網行業比較關注的領域。當業務發展到一定階段的時候,性能網往往會成爲業務發展的主要瓶頸。一個好的應用除了最基本的可以在低併發下對外服務之外,能否支撐高併發訪問是大型互聯網網站比較關心的問題。拿火車訂票網(12306)來說,在平時低併發下都沒有什麼問題,很容易的可以登錄系統,訂到票,一旦到了春節等節假日就出現問題,這點如果在12306上訂過票的同學就比較有感受。CSDN上不乏有牛人站在一個架構師的角度來思考12306。
        支持高併發在流量方面除了單機性能最大化之外另外就是良好的水平擴展能力。單機性能的優化很容易就到達一個極致,而水平擴展可以說是無限的。前段時間在CSDN上看到哪個網站(好像是Amazon)已經達到自動擴容(也就是彈性擴容)的地步。當然這裏會涉及到非常多的領域,這些都不是本文要討論的。OK,回來看看我對流控的一些理解。
      一、爲什麼需要流量監控
      流量監控作爲一個數據收集窗口,不管對開發還是運營都是做出決策和分析問題的一個基礎和有力依據。一個沒有任何監控的系統對於開發和運營而言完全是一場噩夢,因爲系統的運行完全是黑盒。縮小範圍到流控領域,如果沒有監控也就無法判斷當前系統的流量情況,是否需要加機器、是否需要限流、性能的瓶頸在哪裏都不得而知。這些都沒有任何的數據基礎來做出這些決策,流量監控對於當前系統問題排查和後續系統的重構和解藕拆分都有重要的意義。這裏也稍微舉個簡單的例子:比如之前有兩個應用部署在同一臺機器上,由於業務的增長,兩個應用的壓力都隨之增大,通過監控可以實時掌握兩個應用的性能情況,後續兩個應用可以在出現問題之前進行拆分,而不是到問題出現了再解決。
      二、流量監控的粒度
      理論上來講粒度越細越好。實際情況中需要考慮諸多因素,比如實現成本及價值(也就是成本收益)。當前整個系統的情況都會影響在做流控的粒度。一般來講分爲:系統級別>應用級別>方法級別。粒度越細數據收集越多,定位問題和做出決策也會更準確,當然在信息的分析上也要花更多時間。舉個簡單的例子:假設監控是系統級別,一次用戶請求所涉及的應用有10個。現在發現請求非常慢,性能有問題。監控在系統級別的話可以知道系統有問題,但所涉及的10個應用中卻無法知道是哪個或那些應用出了問題。如果是應用級別,就知道哪些應用除了問題。如果是方法級別甚至可以定位到哪個方法的性能有問題。實際場景中這三種粒度的監控都有。可以用來分析不同粒度的問題。對於管理者而言他可能只關心系統級別最多應用級別,而對於開發而言這三個都需要,解決問題則信息越容易找到問題所在。
      三、監控的實現方法
      一般來講監控都會對系統造成一定的侵入性,粒度越細侵入性越強。很多人會想到Spring的aop這種方式來達到對原系統的無侵入監控。實踐證明可行,但實現複雜,對個性化的監控有比較大的侷限性,另外性能的損失也是需要考慮的。往往流量監控不會單獨存在,會承擔一部分決策性工作。比如簡單的說發現目前某應用流量過大,容易導致系統的宕機會啓動限流策略、分流以及服務降級等策略來保證主幹應用的可用。
       實現原理應該說非常簡單,如果一次完整的請求比作一條河流的話,監控相當於水壩。洪水期間其實就相當於超大負荷的請求,爲了不使下游遭殃。“水壩”會啓動一些措施來防止“洪水”到達下游。當然整個防洪的經驗也爲後續的“水壩”加固也提供了數據基礎。淘寶的雙11其實就相當於一次“洪水”。所以淘寶雙11不僅承擔業務上指標,也是爲系統提供一次寶貴的實戰測試。
       四、實踐
       講了這麼多理論來點實踐,我在《學習項目》中對流控做了一個比較有限的實踐,由於沒有真實的高併發場景,模擬的效果也非常有限。這些都放一邊,講講我整個的監控策略,功能實現的非常簡單,主要是其中的一些思想。 
       先上一張UML圖:
           
        核心的類就是FlowMonitor。主要記錄了當前正在運行的線程數,最大瞬時線程數,通過的線程數,丟失線程數。
        這裏解釋一下這幾個詞的含義和產生背景。
運行的線程數:這個比較好理解,監控的當前應用或者方法有多少線程正在運行。
最大瞬時線程數:因爲5分鐘會把上面幾個數據記錄到數據庫,5分鐘內無法記錄到最大的一個瞬時線程,只能記錄記錄的當時的一個運行線程數,這樣對於整個數據是不完整的。
通過的線程數:由於監控的同時會做限流,比如我限制最大的運行線程數爲10,所以當發現最大線程數已經大於我所設置允許最大線程數就會做丟棄處理(當然還會有其他處理策略,我這裏只是以最簡單的方法來描述整個監控的思想)。
丟失的線程數:參考通過的線程數。

介紹了這幾個詞後對整個監控大體上已經知道其工作原理。

下面帖一個具體的實現代碼:
public abstract class MonitorHandler implements Handler{
	
	private static final FlowMonitor flowMonitor = FlowMonitorFactory.regist(AbstractHandler.class.getName());
	
	public void run(){
		//做流控方面的事情
		if(!flowMonitor.entry(this.getClass().getName())){
			return;
		}
		//通過
		try{
			handle();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			//需要釋放資源
			flowMonitor.release(this.getClass().getName());
		}
	}
}
我這裏採用的是侵入性最強的一種應用實現,當然也最簡單,監控的是方法級別的,因爲整個應用場景是一個鏈式處理,只要繼承於MonitorHandler然後配置最大的流量限制閥門就OK了,對於具體的實現者而言還是相對透明的。並非需要他關心整個流控的細節。
tour.ziubao.handler.DispatchHandler=10
上面是一條配置文件,DispatchHandler繼承了MonitorHandler,這樣就可以對DispatchHandler作流量監控。

上面是一張對整個流量監控的展現圖

一個簡單流量監控就完了,我還實現了對於RT(應用響應時間)的監控,由於實現大同小異,就不再作闡述了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章