javamelody对Java Application进行监控

前面写过对于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还有一种简单的方法实现监控

详见:http://code.google.com/p/javamelody/wiki/UserGuideAdvanced#Business_facades_(without_EJB3_and_without_Spring_and_without_Gu

 

具体的集成方式,稍后会在我的github发布出来

 https://github.com/langke93/rest-nettyserver

posted @ 2018-11-27 16:35  程序员宝典  阅读(237)  评论(0编辑  收藏  举报