天天看点

springadmin微服务监控与报警

简介

  • 微服务实践的过程中,我们会发现服务数量众多,如何监测我们哪些服务时正常的、哪些又是亚健康的服务呢?别急,springcloud既然叫微服务全家桶,当然它也有方案啦,我们可以轻松集成springadmin来对我们所有服务的健康状态做监控。
本文将介绍其springadmin如何使用,以及它提供的功能进行说明,内容有
  • springadmin都有哪些功能
  • 搭建安全的、高可用的springadmin监控服务
  • 动态调整日志打印级别
  • 配置服务状态变更邮件报警
  • 查看服状态,包括CPU、内存、磁盘、缓存、DB、MQ各种服务的连接状态等等
  • 查看java虚拟机状态、GC情况和堆栈信息
  • 配置监控springboot1.X版本的集群外服务

原文:传送门

注:本文基于springcloud2.1.3 Greenwich.RELEASE 版本

参考文章

  • spring-admin官方使用教程

1、springadmin都有哪些功能

  • springadmin是用来检测springboot服务状态的监控应用,可以利用springbootactuator暴露出来的endpoint查询服务的一些指标信息
  • springcloud是基于springboot的应用,当然所有的springcloud服务都天然支持整合springadmin进行监控
  • springadmin可以监控服务所在主机的运行状态信息,如cpu、内存、磁盘占用等等
  • 可以监控微服务JVM的线程堆栈信息、GC信息、内存占用情况
  • 可以检测服务内连接DB、缓存服务器、MQ服务等等服务的状态
  • 默认所有的服务连接都是健康状态,整个服务才是UP的,当然我们也可以忽略一些服务的健康检测
  • 线上服务发布后,我们还可以动态调整其日志打印级别,不过这不是持久化的,服务重启后失效
  • 可以查看服务的环境变量信息
  • 服务器的负载情况监测
  • 服务暴露的HTTP接口信息查看
  • 可以下载应用JVM内存快照信息,用来分析内存泄漏很方便,,由于文件一般都很大,需要下载很久,所以需要为此接口特别配置大一点的超时时间
  • 可以配置应用状态变更进行邮件报警

2、搭建安全的、高可用的springadmin监控服务

2.1 服务目录结构如下
┍--- src/main/java
┊
├----- StartServer.java  #服务启动类
┊
├-- src/java/test
┊
├-- src/main/resources
┊
├----- application.yml	#可以把这些信息放在配置中心,发布后可以动态修改报警邮箱和规则等
┊
├----- bootstrap.yml	#服务的基本信息、启动等信息,可以被application.yml中的配置信息覆盖
┊
┕-- pom.xml	
           
2.2 引入依赖信息
  • 编辑pom.xml文件的内容
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  
  	<modelVersion>4.0.0</modelVersion>
	<groupId>com.danyuanblog.springcloud</groupId>
	<artifactId>spring-admin-server</artifactId>
	<name>spring-admin-server</name>
	<url>http://www.danyuanblog.com</url>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.3.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<!-- 定义公共变量 -->
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
		<admin-server.version>2.1.3</admin-server.version>	
	</properties>
	
	<dependencies>
		<!-- springadmin服务器依赖 -->
		<dependency>
			<groupId>de.codecentric</groupId>
			<artifactId>spring-boot-admin-starter-server</artifactId>
			<version>${admin-server.version}</version>
		</dependency>
		<!-- 整合安全服务依赖 -->
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
		<!--整合邮箱报警依赖 -->
        <dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-mail</artifactId>
		</dependency>
		<!-- 监控服务高可用自动集群搭建能力依赖 -->
		<dependency>
		    <groupId>com.hazelcast</groupId>
		    <artifactId>hazelcast</artifactId>
		</dependency>
		<!-- Eureka注册中心客户端依赖 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		
		 <!-- 配置中心客户端依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!-- 服务监控端点暴露依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
		<!-- web服务依赖,容器替换tomcat为jetty,由于tomcat会有个bug -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
		</dependency>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	
	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
		</repository>
		<repository>
			<id>Sonatype</id>
			<name>Sonatype Repository</name>
			<url>http://repository.sonatype.org/content/groups/public</url>
			<layout>default</layout>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>Central</id>
			<name>Central Repository</name>
			<url>http://repo1.maven.org/maven2</url>
			<layout>default</layout>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<name>oss.sonatype.org</name>
			<id>oss.sonatype.org</id>
			<url>http://oss.sonatype.org/content/groups/public</url>
		</pluginRepository>
	</pluginRepositories>
</project>
           
2.3 启动类信息
  • 编辑StartServer.java
package com.danyuanblog.springcloud;

import java.time.Duration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

import com.hazelcast.config.Config;
import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.MergePolicyConfig;
import com.hazelcast.map.merge.PutIfAbsentMapMergePolicy;

import de.codecentric.boot.admin.server.config.AdminServerProperties;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.notify.Notifier;
import de.codecentric.boot.admin.server.notify.RemindingNotifier;
//启用adminServer服务
@EnableAdminServer
//启用服务发现客户端
@EnableDiscoveryClient
@SpringBootApplication
public class StartServer {
	public static void main(String[] args) {
		SpringApplication.run(StartServer.class, args);
	}
	
	@Bean
	public Config hazelcastConfig() {//集群配置
	    MapConfig mapConfig = new MapConfig("spring-boot-admin-event-store").setInMemoryFormat(InMemoryFormat.OBJECT)
	                                                                        .setBackupCount(1)
	                                                                        .setEvictionPolicy(EvictionPolicy.NONE)
	                                                                        .setMergePolicyConfig(new MergePolicyConfig(
	                                                                            PutIfAbsentMapMergePolicy.class.getName(),
	                                                                            100
	                                                                        ));
	    return new Config().setProperty("hazelcast.jmx", "true").addMapConfig(mapConfig);
	}
	
	@Configuration
	public class NotifierConfiguration {
		@Autowired
		private InstanceRepository repository;
	    @Autowired
	    private Notifier notifier;

	    @Primary
	    @Bean(initMethod = "start", destroyMethod = "stop")
	    public RemindingNotifier remindingNotifier() {//告警邮件发送频率配置
	        RemindingNotifier notifier1 = new RemindingNotifier(notifier, repository);
	        //	The reminders will be sent every 10 minutes
	        notifier1.setReminderPeriod(Duration.ofMinutes(10)); 
	        //	Schedules sending of due reminders every 10 seconds.
	        notifier1.setCheckReminderInverval(Duration.ofSeconds(10)); 
	        return notifier1;
	    }
	}
	
	@Configuration
    public static class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
        private final String adminContextPath;

        public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
            this.adminContextPath = adminServerProperties.getContextPath();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
        	//配置springadmin web控制台登录信息和监控端点访问授权开放
            SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
            successHandler.setTargetUrlParameter("redirectTo");
            successHandler.setDefaultTargetUrl(adminContextPath + "/");

            http.authorizeRequests()
                    .antMatchers(adminContextPath + "/assets/**").permitAll()
                    .antMatchers(adminContextPath + "/login").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
                    .logout().logoutUrl(adminContextPath + "/logout").and()
                    .httpBasic().and()
                    .csrf()
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                    .ignoringAntMatchers(
                            adminContextPath + "/instances",
                            adminContextPath + "/actuator/**"
                    );
        }
    }
}
           
2.4 配置信息
  • 编辑bootstap.yml
spring:
  application:
    name: admin-server
  cloud:
    #配置中心相关配置
    config:
      discovery:
        enabled: true
        service-id: config-server
      profile: ${env:dev}   #运行环境,可以通过环境变量进行切换dev,test,stage,prod
      label: master    
      fail-fast: true
      retry:
        initial-interval: 2000        #首次重试间隔时间,默认1000毫秒
        multiplier: 1.1D              #下一次重试间隔时间的乘数,比如开始1000,下一次就是1000*1.1=1100
        max-interval: 5000            #最大重试时间,默认2000
        max-attempts: 50               #最大重试次数,默认6次    
#注册中心相关配置
eureka: 
  client: 
    serviceUrl: 
      defaultZone: http://localhost:8763/eureka/
  instance:
    prefer-ip-address: true
    leaseRenewalIntervalInSeconds: 10
    health-check-url-path: /actuator/health
    #服务端点安全控制,通过eureka来发现服务,自然要配置这里
    metadata-map:
      user.name: ${spring.security.user.name}
      user.password: ${spring.security.user.password}
    
#容器端口配置       
server:
  port: ${port:1202}
#监控端点配置
management:
  endpoint: 
    #启用动态刷新配置功能
    bus-refresh: 
      enabled: true
    #监控端点配置为全覆盖
    health:
      show-details: ALWAYS
  #暴露所有服务端点
  endpoints: 
    web: 
      exposure: 
        include: "*"
           
  • 编辑application.yml
spring: 
  security:
    user: #springadmin登录账号密码配置
      name: admin
      password: 123456
  boot:
    admin:
      monitor: #检测周期和超时时间配置
        period: 180000
        status-lifetime: 180000
        read-timeout: 120000
      ui:
        title: SIMO-E2业务平台服务监控后台

  mail:
    host: smtp.xxx.com
    username: [email protected]
    password: xxxxxx
    default-encoding: UTF-8
    properties:
      mail:
        #这里配置为不开启SSL
        smtp:
          auth: false
          starttls:
            enable: false
            required: false
spring.boot.admin.notify.mail:
  #配置报警通知邮箱号列表,以逗号分隔
  to: [email protected],[email protected],[email protected]
  #邮件发送者
  from: [email protected]
  #开启邮件报警功能
  enabled: true
  #配置应用某些状态变更不通知,A状态->B状态,中间以冒号分隔,常用的如下所示
  #ignore-changes: UNKNOWN:UP,OFFLINE:UP,DOWN:UP,UP:UNKNOWN,OFFLINE:OFFLINE,DOWN:DOWN
  ignore-changes: UNKNOWN:UP  
           
2.5 springcloud服务监控端点配置
  • 微服务只需注册到注册中心,并开启监控端点暴露即可
  • 配置信息如下:
management: 
  endpoint: 
    bus-refresh: 
      enabled: true
    health:
      show-details: ALWAYS
  endpoints: 
    web: 
      exposure: 
        include: "*"  #端点全部开启
           

3、动态调整日志打印级别

  1. 登录进入springadmin web控制台
  2. 打开日志选项卡
  3. 可以看到很多类或包配置的日志打印级别
  4. 现在某个条目的某个日志级别按钮,即可对该包名下或该类的日志级别进行动态调整

4、配置服务状态变更邮件报警说明

服务状态变更均会进行报警,服务有如下几种状态
  • 关闭状态(DOWN)
  • 健康在线状态(UP)
  • 服务已下线(OFFLINE)
  • 未知状态(UNKNOWN)
我们可以配置某些状态变更时不触发邮件报警,具体根据实际情况去配置即可,推荐使用默认的配置即可

5、查看服状态,包括CPU、内存、磁盘、缓存、DB、MQ各种服务的连接状态等等

从springadmin监控后台进入,选择某个实例,进入实例详情页,既可看到这些指标信息

如果发现哪些指标是DOWN的状态,就需要去排查我们的服务哪里有问题了

6、查看java虚拟机状态、GC情况和堆栈信息

通过监控后台页面,我们可以很容易的查看这些信息判断服务的健康情况。

如果还需要更精确的分析服务的健康状态,最好还是使用专业的jvm分析工具。

7、配置监控springboot1.X和2.X版本的集群外服务

7.1 集群外springboot2.X版本的应用监控
  • 引入依赖
<dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>${admin-client.version}</version>
        </dependency>        
           
  • 编辑application.yml
spring:
  application:
    name: service-name
  boot:
    admin: #监控服务相关配置
      client:
        url: http://localhost:1202 #springadminserver地址
        username: admin #spring admin server用户名
        password: 123456 #spring admin server密码
        instance:
          name: ${spring.application.name} #该服务在springadmin中展示的名字配置
          service-url:http://localhost:8282 #此服务暴露给springadmin的地址,用来拉取此服务的健康指标信息
          metadata:
            user.name: admin
            user.password: 123456
            
#监控端点暴露            
management:
  endpoint: 
    health:
      show-details: ALWAYS
  endpoints:     
    web: 
      exposure: 
        include: "*"             
           
7.2 集群外springboot1.X版本的应用监控
  • 引入依赖,admin-client.version跟随项目本身的springboot版本一致就行了
<dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>${admin-client.version}</version>
        </dependency>
           
  • 编辑application.yml
spring:
  application:
    name: service-name
  boot:
    admin:
      client:
        url: http://localhost:1202
        username: admin #spring admin server用户名
        password: 123456 #spring admin server密码
        instance:
          name: ${spring.application.name}
          metadata:
            user.name: ${adminUser:simo}
            user.password: ${adminPass:simo}
endpoints:
  enabled: true
  info.enabled: true  
  health.enabled:true
  security.enabled:false
           
  • springboot1.x版本监控端点暴露配置
参考:springboot1.x endpoint配置说明,需要监控其他端点,可以参考这个文档即可