前面寫過對於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