天天看點

【監控】JavaMelody In ActionJavaMelody In Action

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 端口進行映射的,那如果端口被占用或者我們想換個其他的端口來進行監控資料的話,該怎麼做呢?

  1. pom檔案添加依賴
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
           
  1. 配置檔案設定(yml或者properties檔案),以yml檔案為例
  1. 啟用管理端點并在yml(或properties)中通過http進行端口暴露
management.endpoints.web.exposure.include: info,health,monitoring

javamelody:
  management-endpoint-monitoring-enabled: true
           
  1. 驗證

    http://localhost:8081/actuator/monitoring

大概資訊如下:下面有對應的明細記錄

【監控】JavaMelody In ActionJavaMelody In Action

在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

繼續閱讀