【监控】JavaMelody In Action

    xiaoxiao2025-07-11  7

    JavaMelody In Action

    前言: 在项目的实际运行过程中,我们想知道项目具体运行情况到底是怎么样的,比如,我们关心java虚拟机使用的内存是多少?执行sql的数量及单个sql执行的时间是怎么样的?http 请求有没有错误?定时任务有没有按时触发 …等等,但是,大多数情况这些消息对我们是透明的,我们也很难根据项目的实际运行情况进行针对性的优化。这也就导入了我们今天的主题JavaMelody 。

    JavaMelody

    什么是 JavaMelody JavaMelody是用来在QA和实际运行生产环境中监控Java或Java EE应用程序服务器的一个开源框架。主要基于请求的数据统计来演化图表。

    在Spring Boot项目中使用JavaMelody

    JavaMelody 已经对 Spring Boot 2 有了充分的集成(spring-boot-starter)的支持,但是对于Spring Boot 1 的工程,是不兼容的,不过使用方法与常规的spring项目一致。

    Spring Boot 2 集成 只需要在我们的pom文件里面添加上依赖 <dependency> <groupId>net.bull.javamelody</groupId> <artifactId>javamelody-spring-boot-starter</artifactId> <version>1.77.0</version> </dependency>

    然后我们就可以运行我们的项目,打开url:http://localhost:8080/monitoring 看到对应的监控记录了 我们可以进行对应的针对性的参数设置

    javamelody: # 是否自动装配,default: true enabled: true #排除哪些数据源 excluded-datasources: secretSource,topSecretSource # 启动对service和controller的监控, default: true spring-monitoring-enabled: true # 初始化JavaMelody中的参数 # See: https://github.com/javamelody/javamelody/wiki/UserGuide#6-optional-parameters init-parameters: # log http requests: log: true # 排除对某些url的监控: #url-exclude-pattern: (/webjars/.*|/css/.*|/images/.*|/fonts/.*|/js/.*) # to aggregate digits in http requests: #http-transform-pattern: \d+ # 添加基本的信息验证 #authorized-users: admin:pwd # 设置存储地址: #storage-directory: /tmp/javamelody # 设置监控 "/monitoring" 地址: #monitoring-path: /admin/performance

    具体参数请见: https://github.com/javamelody/javamelody/wiki/UserGuide#6-optional-parameters

    设置默认的url端口 刚才我们谈到,默认的url是需要打开8080 端口进行映射的,那如果端口被占用或者我们想换个其他的端口来进行监控数据的话,该怎么做呢? pom文件添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 配置文件设置(yml或者properties文件),以yml文件为例 management.server.port: 8081 启用管理端点并在yml(或properties)中通过http进行端口暴露 management.endpoints.web.exposure.include: info,health,monitoring javamelody: management-endpoint-monitoring-enabled: true 验证 http://localhost:8081/actuator/monitoring

    大概信息如下:下面有对应的明细记录

    在Spring Boot 1.x 项目中使用JavaMelody

    刚才介绍了在SpringBoot2.0项目中进行组件的集成,那么对于一般的普通Spring Boot 1.x的项目也很简单,所以由此也可以看出来,JavaMelody是一个无侵入性的非常优秀的监控框架

    spring 项目的集成 1)加入pom依赖 <!-- javamelody-core --> <dependency> <groupId>net.bull.javamelody</groupId> <artifactId>javamelody-core</artifactId> <version>1.77.0</version> </dependency> <!-- itext,如果想要pdf导出(不是必须的) --> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> <exclusions> <exclusion> <artifactId>bcmail-jdk14</artifactId> <groupId>bouncycastle</groupId> </exclusion> <exclusion> <artifactId>bcprov-jdk14</artifactId> <groupId>bouncycastle</groupId> </exclusion> <exclusion> <artifactId>bctsp-jdk14</artifactId> <groupId>bouncycastle</groupId> </exclusion> </exclusions> </dependency>

    如果你想要导出xml或者json 的报告,需要这两个依赖(不是必须的)

    <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.10</version> </dependency> <dependency> <groupId>org.jrobin</groupId> <artifactId>jrobin</artifactId> <version>1.5.9</version> </dependency>

    2)复制下面的配置类

    package hello; import java.util.Arrays; import java.util.EventListener; import java.util.HashSet; import java.util.Map; import javax.servlet.DispatcherType; import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; import javax.sql.DataSource; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.aop.support.Pointcuts; import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import net.bull.javamelody.MonitoredWithAnnotationPointcut; import net.bull.javamelody.MonitoredWithSpring; import net.bull.javamelody.MonitoringFilter; import net.bull.javamelody.MonitoringSpringAdvisor; import net.bull.javamelody.Parameter; import net.bull.javamelody.SessionListener; import net.bull.javamelody.SpringContext; import net.bull.javamelody.SpringDataSourceBeanPostProcessor; import net.bull.javamelody.SpringRestTemplateBeanPostProcessor; /** * Spring configuration for JavaMelody. * */ @Configuration @ConditionalOnWebApplication public class JavaMelodyConfiguration { /** * Name of the FilterRegistrationBean. */ public static final String REGISTRATION_BEAN_NAME = "javamelody-registration"; /** * Registers the JavaMelody {@link SessionListener}. * @param servletContext ServletContext * @return ServletListenerRegistrationBean */ @Bean public ServletListenerRegistrationBean<EventListener> monitoringSessionListener( ServletContext servletContext) { final ServletListenerRegistrationBean<EventListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>( new SessionListener()); if (servletContext.getFilterRegistration("javamelody") != null) { // if webapp deployed as war in a container with MonitoringFilter and SessionListener already added by web-fragment.xml, // do not add again servletListenerRegistrationBean.setEnabled(false); } return servletListenerRegistrationBean; } /** * Registers the JavaMelody {@link MonitoringFilter}. * @param servletContext ServletContext * @return FilterRegistrationBean */ @Bean(name = REGISTRATION_BEAN_NAME) public FilterRegistrationBean monitoringFilter(ServletContext servletContext) { final FilterRegistrationBean registrationBean = new FilterRegistrationBean(); // Create the monitoring filter and set its configuration parameters. final MonitoringFilter filter = new MonitoringFilter(); filter.setApplicationType("Spring Boot"); // Wrap the monitoring filter in the registration bean. registrationBean.setFilter(filter); registrationBean.setAsyncSupported(true); registrationBean.setName("javamelody"); registrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC); // Set the initialization parameter for the monitoring filter. // see the list of parameters: // https://github.com/javamelody/javamelody/wiki/UserGuide#6-optional-parameters registrationBean.addInitParameter(Parameter.LOG.getCode(), Boolean.toString(true)); // to exclude images, css, fonts and js urls from the monitoring: // javaMelody.addInitParameter(Parameter.URL_EXCLUDE_PATTERN.getCode(), "(/webjars/.*|/css/.*|/images/.*|/fonts/.*|/js/.*)"); // to add basic auth: // javaMelody.addInitParameter(Parameter.AUTHORIZED_USERS.getCode(), "admin:pwd"); // to change the default storage directory: // javaMelody.addInitParameter(Parameter.STORAGE_DIRECTORY.getCode(), "/tmp/javamelody"); // Set the URL patterns to activate the monitoring filter for. registrationBean.addUrlPatterns("/*"); final FilterRegistration filterRegistration = servletContext .getFilterRegistration("javamelody"); if (filterRegistration != null) { // if webapp deployed as war in a container with MonitoringFilter already added by web-fragment.xml, // do not try to add it again registrationBean.setEnabled(false); for (final Map.Entry<String, String> entry : registrationBean.getInitParameters() .entrySet()) { filterRegistration.setInitParameter(entry.getKey(), entry.getValue()); } } return registrationBean; } // Note: if you have auto-proxy issues, you can add the following dependency in your pom.xml: // <dependency> // <groupId>org.springframework.boot</groupId> // <artifactId>spring-boot-starter-aop</artifactId> // </dependency> @Bean @ConditionalOnMissingBean(DefaultAdvisorAutoProxyCreator.class) public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { return new DefaultAdvisorAutoProxyCreator(); } /** * Monitoring of JDBC {@link DataSource}s * @param excludedDatasources Comma separated list of excluded datasources * @return SpringDataSourceBeanPostProcessor */ @Bean public SpringDataSourceBeanPostProcessor monitoringDataSourceBeanPostProcessor( @Value("${javamelody.excluded-datasources:}") String excludedDatasources) { final SpringDataSourceBeanPostProcessor processor = new SpringDataSourceBeanPostProcessor(); if (excludedDatasources != null && excludedDatasources.trim().length() > 0) { processor.setExcludedDatasources( new HashSet<>(Arrays.asList(excludedDatasources.split(",")))); } return processor; } /** * Monitoring of beans and methods having the {@link MonitoredWithSpring} annotation. * @return MonitoringSpringAdvisor */ @Bean public MonitoringSpringAdvisor monitoringSpringAdvisor() { return new MonitoringSpringAdvisor(new MonitoredWithAnnotationPointcut()); } /** * Monitoring of beans having the {@link Service} annotation. * @return MonitoringSpringAdvisor */ @Bean public MonitoringSpringAdvisor monitoringSpringServiceAdvisor() { return new MonitoringSpringAdvisor(new AnnotationMatchingPointcut(Service.class)); } /** * Monitoring of beans having the {@link Controller} annotation. * @return MonitoringSpringAdvisor */ @Bean public MonitoringSpringAdvisor monitoringSpringControllerAdvisor() { return new MonitoringSpringAdvisor(new AnnotationMatchingPointcut(Controller.class)); } /** * Monitoring of beans having the {@link RestController} annotation. * @return MonitoringSpringAdvisor */ @Bean public MonitoringSpringAdvisor monitoringSpringRestControllerAdvisor() { return new MonitoringSpringAdvisor(new AnnotationMatchingPointcut(RestController.class)); } /** * Monitoring of beans or methods having the {@link Async} annotation. * @return MonitoringSpringAdvisor */ @Bean public MonitoringSpringAdvisor monitoringSpringAsyncAdvisor() { return new MonitoringSpringAdvisor( Pointcuts.union(new AnnotationMatchingPointcut(Async.class), new AnnotationMatchingPointcut(null, Async.class))); } /** * Monitoring of beans methods having the {@link Scheduled} or {@link Schedules} annotations. * @return MonitoringSpringAdvisor */ // @Bean // public MonitoringSpringAdvisor monitoringSpringScheduledAdvisor() { // return new MonitoringSpringAdvisor( // Pointcuts.union(new AnnotationMatchingPointcut(null, Scheduled.class), // new AnnotationMatchingPointcut(null, Schedules.class))); // } /** * Monitoring of {@link RestTemplate} beans. * @return SpringRestTemplateBeanPostProcessor */ @Bean public SpringRestTemplateBeanPostProcessor monitoringRestTemplateBeanPostProcessor() { return new SpringRestTemplateBeanPostProcessor(); } /** * @return Reference to the Spring context. */ @Bean public SpringContext javamelodySpringContext() { return new SpringContext(); } }

    正常情况下,这个时候已经能够正常运行了,如果不能运行,检查是否动态代理有问题,如果有问题的话添加aop包

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>

    在Spring MVC 项目中使用JavaMelody

    整合到Spring 项目中 1)添加POM依赖 <!--JavaMelody监控--> <dependency> <groupId>net.bull.javamelody</groupId> <artifactId>javamelody-core</artifactId> <version>1.74.0</version> </dependency>

    2)在Spring-config.xml中导入配置

    <!--javamelody 监控--> <import resource="classpath:net/bull/javamelody/monitoring-spring.xml"/> <import resource="classpath:net/bull/javamelody/monitoring-spring-datasource.xml"/> <import resource="classpath:net/bull/javamelody/monitoring-spring-aspectj.xml"/>

    启动项目,然后打开url:http://localhost:8080/monitoring 检验下结果吧!

    参考:https://github.com/javamelody/javamelody

    最新回复(0)