系統性能監控系列1:使用JAVA動態代理實現非侵入式的效能測量方法
歡迎關注公眾號:
當我們開發的服務上線後,線上的系統執行狀態(是否正常,效能是否滿足需求)等等就成了架構師和研發工程師關心的問題 。對於系統監控有很多維度,比如:監控CPU,磁碟IO,監控服務請求的響應時間等。相對於這些來說,我今天要給大家分享的是具體的程式碼層次的效能測量。
有過一定開發經驗的朋友,在程式碼遇到效能問題的時候,需要對程式碼進行效能測量。一般的方法是:在呼叫每一個目標方法是啟動效能監視,在目標方法結束後計算執行時間並輸出到console或者是log中,以遍進行程式碼效能的分析。我們首先討論侵入式效能測量方法。
一、侵入式效能測量方法:
我們在進行業務開發的時候通常會設計一個業務介面,然後在讓具體實現類繼承介面,實現具體的業務功能。這裡我定義了一個UserService介面如圖下
下面我們來看下UserService介面的具體實現類,如下圖所示:
圖1
PerformanceMonitor工具類的定義如下:
圖2
如果要想測量doSomething的執行效能,我們需要在doSomething的方法中加入效能測量程式碼(如圖1紅框中程式碼所示)。當我們有很多的函式需要測量,那麼像如上圖1所示UserServiceNoPorxyImpl的實現的話,我們需要做很多的重複工作,需要把對PerformanceMonitor的呼叫複製到所有需要測量的函式內部。這是一個繁瑣而且沒有工作效率的事情。最恐怖的是,這些程式碼摻雜在正常的業務程式碼中,影響後期系統維護。那麼有沒有好辦法解決這個問題呢?答案是有。
二、JAVA的動態代理機制效能測量方法
動態代理是JDK1.3之後提供的開發技術,它允許開發者在程式執行期間建立介面的代理例項。JDK的動態代理主要涉及到java.lang.reflect包中的兩個類:Proxy和InvocationHandler。InvocationHandler是一個介面。可以通過實現該介面進行效能測量方法。關於動態代理的具體細節請大家Google下。在這裡就不贅述了。
首先我們刪除了doSomething中的效能測量程式碼,如下所示:
圖3
從上圖中可以看出,改寫後的UserService實現類中方法doSomething中已經將效能測量程式碼都去掉了,只剩下業務邏輯程式碼,是不是很清爽?
那麼問題來了,既然doSomething中沒有了效能測量程式碼,我們怎麼能夠實現具體的效能測量呢。這是我們就需要InvocationHandler介面的幫助了,我們將效能測量程式碼實現在InvocationHandler介面的實現類PerformanceHandler中,程式碼如下圖所示:
PerfomaceHandler關鍵所在如上圖中③所示(呼叫業務目標的方法,在我們這裡就是呼叫doSomething方法)。
具體呼叫過程如圖3紅框中所示,我們需要使用到Proxy類的newProxyInstance靜態方法來動態建立一個UserService的代理介面。該方法的第一個引數是類載入器,第二個引數是建立代理例項所需要實現的一組介面,第三個引數是InvocationHandler。
通過測試,我們發現上述程式碼和侵入式效能測試程式碼的效果一致。我們通過使用JAVA的動態代理機制我們把效能測試程式碼和業務邏輯程式碼解耦。