前兩天在看Spring內(nèi)置的攔截器的時候,發(fā)現(xiàn)了一個之前沒有注意的
類:org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor,
好奇心促使我上網(wǎng)查了一下這個jamon。大概看了一下之后發(fā)現(xiàn)這個玩意還真挺好用的而且挺重要的,而且現(xiàn)在國內(nèi)對它的介紹也很少,所以寫了一篇文章和大
家分享。
一,Jamon簡介:
Jamon的全名是:Java Application
Monitor。它是一個小巧的,免費(fèi)的,高性能的,線程安全的性能監(jiān)測工具。它可以用來測定系統(tǒng)的性能瓶頸,也可以用來監(jiān)視用戶和應(yīng)用程序之間的交互情
況。 Jamon主要是用來檢測jee的應(yīng)用程序。它最新的版本是2.1,可以用在1.4以上的jdk上。
二,將jamon導(dǎo)入到你的應(yīng)用程序中去
首先下載jamon的開發(fā)包,見我的附件,同時你也可以去Sourceforge上自己下載。Sourceforge的下載地址為
http://jamonapi.sourceforge.net。解壓之后可以得到一個jar包和一個war包。jar包是自己會用到的,而war包是
一個例子(不要小看這個例子,待會也要把它導(dǎo)入到項(xiàng)目中)。把war包之間丟到服務(wù)器上,訪問:localhost:8080/jamon就可以看到這個
例子了,這個例子是一個簡單的性能監(jiān)控系統(tǒng)。
接著把例子中的所有的包都導(dǎo)入到項(xiàng)目中,并把war包中的jsp和images還有css都考到項(xiàng)目中,比如新建一個目錄叫monitor(它和WEB-INF是同級目錄)。
三,正確配置自己的應(yīng)用
我們在性能監(jiān)測的時候最監(jiān)測的就是頁面的訪問率和類中方法的訪問率。所以在這一部分主要講解一下如何監(jiān)測自己的頁面和類中方法的訪問。
1, 檢測自己的頁面訪問率
首先我們需要在web.xml中添加一個filter,這個filter就是用來判斷哪些頁面需要被監(jiān)視的,如下所示:
- <filter>??
- ????????<filter-name>JAMonFilter</filter-name>??
- ????????<filter-class>com.easywebwork.filter.EasyPageMonFilter</filter-class>??
- ????</filter>??
- ????<filter-mapping>??
- ????????<filter-name>JAMonFilter</filter-name>??
- ????????<url-pattern>/*</url-pattern>??
- ????</filter-mapping>??
<filter>
<filter-name>JAMonFilter</filter-name>
<filter-class>com.easywebwork.filter.EasyPageMonFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>JAMonFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
接下來我們看看這個filter的寫法:
- ?
- ?
- ?
- ?
- ??
- public?class?PageMonFilter?extends?JAMonFilter{??
- ??
- ????private?static?final?long?serialVersionUID?=?5746197114960908454L;??
- ??
- ????public?void?doFilter(ServletRequest?request,?ServletResponse?response,?FilterChain?filterChain)?throws?IOException,?ServletException?{??
- ?????????Monitor?allPages?=?MonitorFactory.start(new?MonKeyImp("org.easywebwork.allPages",getURI(request),"ms."));??
- ???????????
- ?????????Monitor?monitor?=?MonitorFactory.start(getURI(request));??
- ???????????
- ?????????try?{??
- ??????????filterChain.doFilter(request,?response);??
- ?????????}?finally?{??
- ??????????monitor.stop();??
- ??????????allPages.stop();??
- ?????????}??
- ???????}??
- ??
- ???????protected?String?getURI(ServletRequest?request)?{??
- ?????????if?(request?instanceof?HttpServletRequest)?{??
- ???????????return?((HttpServletRequest)?request).getRequestURI();??
- ?????????}??else?{??
- ???????????return?"Not?an?HttpServletRequest";??
- ?????????}??
- ???????}??
- ??
- ???????private?FilterConfig?filterConfig?=?null;??
- ?????????
- }}??
/**
* @author 張榮華(ahuaxuan)
*
* @since 2007-8-13
*/
public class PageMonFilter extends JAMonFilter{
private static final long serialVersionUID = 5746197114960908454L;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
Monitor allPages = MonitorFactory.start(new MonKeyImp("org.easywebwork.allPages",getURI(request),"ms."));
//這里就是我們要監(jiān)視的所有的頁面的配置
Monitor monitor = MonitorFactory.start(getURI(request));
//這里就是我們要監(jiān)視的某個頁面的配置
try {
filterChain.doFilter(request, response);
} finally {
monitor.stop();
allPages.stop();
}
}
protected String getURI(ServletRequest request) {
if (request instanceof HttpServletRequest) {
return ((HttpServletRequest) request).getRequestURI();
} else {
return "Not an HttpServletRequest";
}
}
private FilterConfig filterConfig = null;
}}
這個類看上去很簡單,其實(shí)也挺簡單的,就是得到uri,然后把它注冊到MonitorFactory類中。這樣只要我們?nèi)ピL問剛才創(chuàng)建的monitor目錄下的jsp就可以看到性能監(jiān)測頁面了。
2,
,接下來我們看看在使用spring的情況下如何監(jiān)測一個bean的方法調(diào)用。Spring也提供了對Jamon的支持(spring支持的東西還真多
啊),也就是文章開頭提出的那個攔截器,為了給我們的bean加上攔截器,我們在spring的applicationcontext配置文件中加入如下
語句:
- <bean?class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">??
- ????????<property?name="beanNames">??
- ????????????<list>??
- ????????????????<value>userService</value>????????????????
- ????????????</list>??
- ????????</property>??
- ????????<property?name="interceptorNames">??
- ????????????<list>??
- ????????????????<value>jamonInterceptor</value>??
- ????????????</list>??
- ????????</property>??
- ????</bean>??
- ??????
- ????<bean?id="jamonInterceptor"?class="org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor">??
- </bean>??
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>userService</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>jamonInterceptor</value>
</list>
</property>
</bean>
<bean id="jamonInterceptor" class="org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor">
</bean>
上面這個是典型的spring的aop的配置,如果對spring的aop配置不了解的可以去看一下spring中文文檔,當(dāng)然如果不想了解的話即使直接把這段配置拷到自己的項(xiàng)目中也是可以直接使用的。
還有一個步驟就是在你的log4j.properties中加入這句代碼:
- log4j.logger.org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor?=?TRACE??
log4j.logger.org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor = TRACE
如果沒有這一行,那么這個攔截器是不會把方法調(diào)用的信息向MonitorFactory注冊的。
只需要這些步驟,userservice中的方法在調(diào)用的時候就可以被攔截,然后將其注冊到MonitorFactory中去了。
所有的配置完成之后我們來看一下效果吧:
http://www.javaeye.com/topics/download/b2bac96e-6c18-4340-b7e0-f84c7bb6adca從這個圖上我們可以看到,所有頁面被訪問的次數(shù),UserService中的getAllUsers被調(diào)用的次數(shù),最右邊的是訪問時間。這只是整個圖的一部分,當(dāng)然這個頁面中也包括每一個頁面被訪問的次數(shù)和第一次訪問的時間等等。下載附件運(yùn)行,就可以看到所有的頁面了。
三,總結(jié)
根據(jù)以上的步驟,我們就可以監(jiān)測我們的程序了,應(yīng)用程序中哪些頁面被訪問的多,哪些頁面被訪問的少,哪些方法被訪問的多,哪些方法被訪問的少,以
及訪問高峰期集中在什么時間等等,有了這些參數(shù),我們更可以有針對性的對應(yīng)用程序進(jìn)行優(yōu)化了,比如說某個頁面訪問比較頻繁,我就可以用ehcache或
oscache給這個頁面做一個緩存。如果某個方法的訪問比較頻繁那就看看這個方法能否進(jìn)一步優(yōu)化,是需要異步,還是需要緩存,還是需要其他等等,總之有
了jamon可以給我們帶來更多的便捷,既可以讓我們知道我們的客戶的行為,也可以讓我們知道我們開發(fā)的程序的“能力”。
其實(shí)本文提供的只是對頁面和方法調(diào)用的監(jiān)控,但是jamon可以提供更多功能,比如說sql語句的監(jiān)控等等,這就需要我們共同去發(fā)掘了。
附件中包括了一個easywebwork的例子,我把jamon導(dǎo)入到這個例子工程中去,大家可以直接下載運(yùn)行觀看效果。Easywebwork是一個旨在減少webwork2.2.x系列的xml配置文件的項(xiàng)目,
如果對這個主題感興趣請到
http://www.javaeye.com/topic/91614http://www.javaeye.com/topic/93814參加討論。