前面写过对于webapp,用javamelody来监控、分析性能是挺方便的;那要对普通的java应用进行监控,只需要在应用上启动一个嵌入式web容器就可以了。
javamelody里面的war包就用了winstone 作为Servlet容器,可以直接启动;本文是以Jetty为例,在应用中嵌入一个jetty:
import java.util.EventListener; import java.util.HashMap; import java.util.Map; import javax.servlet.Filter; import org.mortbay.jetty.Connector; import org.mortbay.jetty.Handler; import org.mortbay.jetty.Server; import org.mortbay.jetty.bio.SocketConnector; import org.mortbay.jetty.handler.ContextHandlerCollection; import org.mortbay.jetty.handler.ResourceHandler; import org.mortbay.jetty.servlet.Context; import org.mortbay.jetty.servlet.DefaultServlet; import org.mortbay.jetty.servlet.FilterHolder; import org.mortbay.thread.QueuedThreadPool; import org.springframework.web.context.ContextLoaderListener; /** * 启动一个jetty容器,结合javamelody用于监控应用性能 * @author langke * 2012-12-21 */ public class JavaMelodyMonitorServer { private ESLogger log = Loggers.getLogger(JavaMelodyMonitorServer.class); Server webServer; /** * * @param serverName 应用名称 * @param host 绑定的IP地址 * @param serverPort 应用端口,jetty启动的端口默认会在此基础上加1000,如果配置文件有配置jetty.listen.port则配置优先 */ public JavaMelodyMonitorServer(String serverName,String host,int serverPort) { init(serverName, host, serverPort); start(); final JavaMelodyMonitorServer server = this; Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { try { log.info("shutdown mointorServer:{}", server); server.stop(); } catch (Exception e) { log.error("run main stop error!", e); } } }); } private void init(String serverName,String host,int serverPort){ int defaultValue = serverPort+1000; int port = Config.get().getInt("jetty.listen.port", defaultValue); Connector connector = new SocketConnector(); webServer = new Server(); QueuedThreadPool pool = new QueuedThreadPool(); pool.setMinThreads(Config.get().getInt("jetty.pool.MinThread", 3)); pool.setMaxThreads(Config.get().getInt("jetty.pool.MaxThread", 32)); String server = host; pool.setName(serverName+"-monitor"); pool.setDaemon(true); webServer.setThreadPool(pool); connector = new SocketConnector(); connector.setPort(port); connector.setHost(server); connector.setMaxIdleTime(60000); // 1 min webServer.addConnector(connector); ContextHandlerCollection col = new ContextHandlerCollection(); Context context = new Context(col, "/", Context.SESSIONS); ResourceHandler resourceHandler = new ResourceHandler(); webServer.setHandlers(new Handler[] {col,resourceHandler }); webServer.addHandler(context); // Set Java Melody storage Directory System.setProperty("javamelody.storage-directory", "javamelody-"+pool.getName()); //add filter Filter monitoringFilter = new net.bull.javamelody.MonitoringFilter(); context.addFilter(new FilterHolder(monitoringFilter), "/monitoring", Handler.REQUEST); Map<String,String> initParams = new HashMap<String,String>(); initParams.put("contextConfigLocation", "classpath:net/bull/javamelody/monitoring-spring.xml"); context.setInitParams(initParams); //add listener EventListener listener = new ContextLoaderListener(); context.addEventListener(listener); context.addServlet(DefaultServlet.class, "/*"); } private void start(){ try{ webServer.join(); webServer.start(); }catch (Exception e){ log.error("Error starting httpserver", e); } } private void stop(){ try{ webServer.stop(); webServer.destroy(); }catch (Exception e){ log.error("Error stop httpserver", e); } } }
这个jetty加了shutdown hook,应用关闭的时候会自己关闭容器。
然后在你的Application里实例化这个类就行了;
需要的jar依赖名如下:
servlet-api-3.0.jar
org.springframework.web-3.1.0.RELEASE.jar
jrobin-1.5.9.1.jar
jetty-util-6.1.26.jar
jetty-6.1.26.jar
javamelody.jar
com.springsource.net.sf.cglib-2.2.0.jar
如果使用spring框架,监控配置就比较简单,可以对某个包所有类进行监控:
<bean id="facadeMonitoringAdvisor" class="net.bull.javamelody.MonitoringSpringAdvisor"> <property name="pointcut"> <bean class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value="org.langke.core.service.*" /> </bean> </property> </bean>
监控数据源:
<bean id="springDataSourceBeanPostProcessor" class="net.bull.javamelody.SpringDataSourceBeanPostProcessor"> </bean> <bean id="wrappedDataSource" class="net.bull.javamelody.SpringDataSourceFactoryBean"> <property name="targetName" value="dataSource" /> </bean>
还有一种方式:注解
只需添加注解@net.bull.javamelody.MonitoredWithGuice在你的实现类或者你要监控的方法:使用net.bull.javamelody.MonitoringProxy类代理
详见:http://code.google.com/p/javamelody/wiki/UserGuide#10._Business_facades_(if_Guice)
如果不用Spring也不用Guice还有一种简单的方法实现监控
具体的集成方式,稍后会在我的github发布出来
https://github.com/langke93/rest-nettyserver