Faceți căutări pe acest blog

joi, 17 mai 2012

JETM performance monitoring for Apache James

The story

Today I decided to improve how people can monitor Apache James email server. James already has some monitoring available via: Each of the above monitoring options is useful and necessary as it's used to monitor different aspects of how James runs. With regard to performance, only JMX monitoring can provide metrics that allow a user to get a feel of the server state.
With JMX enabled you can just launch jconsole to access the attributes and methods that James exposes: number of active connections active per component, limits, etc. You have complete monitoring access to the following services:
  • IMAP
  • POP3
  • SMTP
  • LMTP
  • RemoteManager
  • DNSService
  • Queues

The nice thing about JMX is that it's integrated with the JVM (no external libraries also) and can provide very precise information on almost every aspect of your application like memory, execution of methods, number of method calls, etc. You can see what James exposes on the Java Management Extension page. JMX is good so why another solution to monitor James? Well, in order for JMX monitoring to work you have to write some code and once you get it in there it's not easy to turn off. Since James is component based, disabling JMX is very easy: you just have to comment out some spring beans declarations. So the second part is not an issue, but the first one is.
Monitoring all James components means you have to write code for each component. This will make the code-base larger and harder to maintain. Here's where Java™ Execution Time Measurement Library or JETM shines. It's a general library that you can use in your application to do monitoring. It's small, compact, adds little overhead and provides all the basic stuff that you need, including an web interface to view your results.
The nicest part about JETM is that it has spring integration. Because James uses spring extensively (the IOC part) integrating the two was a matter of a few hours (took my time reading).

How it works

The JETM library has integration with spring framework and uses spring AOP. It creates a Proxy to intercept calls to the beans that you wish to monitor.

The result

and detailed:

The code

You won't find much here, just some configurations. You can see the full diff here.
In a few words: add the library to your project pom.xml file:
        <dependencies>
<dependency>
<groupId>fm.void.jetm</groupId>
<artifactId>jetm</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>fm.void.jetm</groupId>
<artifactId>jetm-optional</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
Next declare the monitoring beans in your project (jetm-monitoring.conf in our case):
    <bean id="etmMonitor" class="etm.core.monitor.NestedMonitor"
init-method="start" destroy-method="stop" />
<bean id="etmHttpConsole" class="etm.contrib.console.HttpConsoleServer"
init-method="start" destroy-method="stop" autowire="constructor"/>

<bean id="etmMethodCallInterceptor"
class="etm.contrib.aop.aopalliance.EtmMethodCallInterceptor"
autowire="constructor"/>

<bean id="etmAutoProxy"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>etmMethodCallInterceptor</value>
</list>
</property>
Here EtmMonitor is responsible for collecting and aggregating measurements points. The measurements points are method calls intercepted by EtmMethodCallInterceptor. The final step is to add the list of beans from your project that you wish to monitor (also in jetm-monitoring.conf). Here I added most of the beans exported by James.

    <bean id="etmAutoProxy"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>etmMethodCallInterceptor</value>
</list>
</property>
<!-- add the beans that you wish to monitor to the list bellow -->
<property name="beanNames">
<list>
<value>usersrepository</value>
<value>recipientrewritetable</value>
<value>domainlist</value>
<value>mailrepositorystore</value>
<!--
The folowing beans require CGLIB2 to be on the classpath -->
<!--
<value>mailqueuefactory</value>
<value>blobTransferPolicy</value>
<value>jmsConnectionFactory</value>
-->
<value>jmsTransactionManager</value>
<value>mailprocessor</value>
<value>mailetcontext</value>
<value>mailspooler</value>
<value>mailetloader</value>
<value>matcherloader</value>
<value>filesystem</value>
<value>dnsservice</value>
<value>fetchmail</value>
<value>smtpserver</value>
<value>pop3server</value>
<value>lmtpserver</value>
<value>imapserver</value>
<value>imapDecoder</value>
<value>imapEncoder</value>
<value>locker</value>
<value>datasource</value>
</list>
</property>
</bean>
Spring will do the rest (we import the jetm-monitoring.conf in spring-server.xml to bring it in context).

Final notes

You can do much more than what I've showed. You can export the metrics JETM collects via JMX and console, not just HTTP console. Please read the online docs for more details.
You can get the source code as example by checking out James App . After discussing this on James mailing list a number of other promising monitoring libraries turned up: metrics from Codehale and Servo from Netflix. They both deserve a look.

Un comentariu: