如果你正在使用Spring管理/訪問資源(Dao/Service),那麼你可能也需要添加一些基礎的性能監控。在Spring AOP的幫助下這將變成一個簡單的任務,不需要任何現有代碼的變化,只是一些簡單的配置。

 

第一步,你首先的將spring-aop、aspectj和cglib庫導入,如果你使用maven管理你的項目依賴的話,很簡單加上如下依賴關系就可以了。








01 <dependency>



02 <groupId>org.aspectj</groupId>



03 <artifactId>aspectjweaver</artifactId>



04 <version>1.5.4</version>



05 </dependency>



06 <dependency>



07 <groupId>cglib</groupId>



08 <artifactId>cglib-nodep</artifactId>



09 <version>2.2</version>



10 </dependency>



11 <dependency>



12 <groupId>org.springframework</groupId>



13 <artifactId>spring-aop</artifactId>



14 <version>2.5.6</version>



15 </dependency>




接下來,指明你需要監視的內容,並把AOP配好。通常,僅僅需要在現有的SpringXML設定檔中增加一個橫切點。這個配置將會將位於包"com.mycompany.services"下的所有方法的響應時間記錄下來。注:這些類必須使用Spring coNtext初始化,否則AOP將不會被執行。








1 <bean id="performanceMonitor"



2 class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor" />



3



4 <aop:config>



5 <aop:pointcut id="allServiceMethods" expression="execution(* com.mycompany.services.*.*(..))"/>



6 <aop:advisor pointcut-ref="allServiceMethods" advice-ref="performanceMonitor" order="2"/>



7 </aop:config>




接下來,需要配置好日誌系統,例如log4j。








1 <logger name="org.springframework.aop.interceptor.PerformanceMonitorInterceptor" additivity="false">



2 <level value="TRACE"/>



3 <appender-ref ref="STDOUT"/>



4 </logger>




ok了,現在我們運行一下程式你會發現下面的日誌輸出:








1 TRACE PerformanceMonitorInterceptor - StopWatch 'PerfTestService.processRequest': running time (millis) = 1322



2 TRACE PerformanceMonitorInterceptor - StopWatch 'PerfTestService.processRequest': running time (millis) = 98



3 TRACE PerformanceMonitorInterceptor - StopWatch 'PerfTestService.processRequest': running time (millis) = 1764




這些是大量的一些原始數據,但不幸的是這些東西對我們幾乎沒用,每一個方法調用都會有記錄,而且缺乏一些其他資訊。所以,除非你打算寫一些日誌分析程式、或者使用協力廠商軟件,否則的話,我想你應該在日誌被記錄前做出一些處理。

 

一個簡單的辦法就是在這之間寫一個簡單的攔截器類來替代Spring給我們提供的默認的類(PerformanceMonitorInterceptor)。下面的一個例子,這個例子提供了一些有用的資訊(最後一個、平均、最大的響應時間),另外當一個方法的響應時間超出指定的時間後給出警告。

 

默認的,每當十個方法調用的時候,做一次記錄,在任何方法響應時間超過1000ms的時候給出警告。







01 public class PerfInterceptor implements MethodInterceptor {



02



03 Logger logger = LoggerFactory.getLogger(PerfInterceptor.class.getName());



04 private static ConcurrentHashMap<String, MethodStats> methodStats = new ConcurrentHashMap<String, MethodStats>();



05 private static long statLogFrequency = 10;



06 private static long methodWarningThreshold = 1000;



07



08 public Object invoke(MethodInvocation method) throws Throwable {



09 long start = System.currentTimeMillis();



10 try {



11 return method.proceed();



12 }



13 finally {



14 updateStats(method.getMethod().getName(),(System.currentTimeMillis() - start));



15 }



16 }



17



18 private void updateStats(String methodName, long elapsedTime) {



19 MethodStats stats = methodStats.get(methodName);



20 if(stats == null) {



21 stats = new MethodStats(methodName);



22 methodStats.put(methodName,stats);



23 }



24 stats.count++;



25 stats.totalTime += elapsedTime;



26 if(elapsedTime > stats.maxTime) {



27 stats.maxTime = elapsedTime;



28 }



29



30 if(elapsedTime > methodWarningThreshold) {



31 logger.warn("method warning: " + methodName + "(), cnt = " + stats.count + ", lastTime = " + elapsedTime + ", maxTime = " + stats.maxTime);



32 }



33



34 if(stats.count % statLogFrequency == 0) {



35 long avgTime = stats.totalTime / stats.count;



36 long runningAvg = (stats.totalTime-stats.lastTotalTime) / statLogFrequency;



37 logger.debug("method: " + methodName + "(), cnt = " + stats.count + ", lastTime = " + elapsedTime + ", avgTime = " + avgTime + ", runningAvg = " + runningAvg + ", maxTime = " + stats.maxTime);



38



39 //reset the last total time



40 stats.lastTotalTime = stats.totalTime;



41 }



42 }



43



44 class MethodStats {



45 public String methodName;



46 public long count;



47 public long totalTime;



48 public long lastTotalTime;



49 public long maxTime;



50



51 public MethodStats(String methodName) {



52 this.methodName = methodName;



53 }



54 }



55 }




現在,你只需要將你的Spring設定檔中做相關修改,將這個類應用進去,再運行程式,你將會看到如下的統計資訊。







1 WARN PerfInterceptor - method warning: processRequest(), cnt = 10, lastTime = 1072, maxTime = 1937



2 TRACE PerfInterceptor - method: processRequest(), cnt = 10, lastTime = 1072, avgTime = 1243, runningAvg = 1243, maxTime = 1937



3 WARN PerfInterceptor - method warning: processRequest(), cnt = 20, lastTime = 1466, maxTime = 1937



4 TRACE PerfInterceptor - method: processRequest(), cnt = 20, lastTime = 1466, avgTime = 1067, runningAvg = 892, maxTime = 1937




正如你看到的一樣,這些統計數據可以在不修改任何現有的JAVA代碼的情況下,提供有關class/method性能的有價值的反饋,而根據這個日誌,你可以很輕松的找出程式中的瓶頸。
 
From:CSDN
創作者介紹
創作者 shadow 的頭像
shadow

資訊園

shadow 發表在 痞客邦 留言(0) 人氣()