SpringBoot Admin 应用监控


 

概述

大型分布式系统都应该提供监控功能,监控系统各部分的运行状态。
 

监控的好处

  • 便于查看分布式系统各个节点的运行状态,及时发现可能存在的隐患
  • 系统故障时便于排查
  • 可根据监控提供的qps、硬件使用情况等针对性地对系统进行优化
     

监控维度

  • cpu、内存、硬盘、带宽等硬件的使用情况
  • db、redis、tomcat、kafka等组件的状态、相关指标
  • 接口qps、响应时间的95线|99线等应用本身的指标
     

springboot提供的actuator可以监控应用,但需要访问actuator相关接口查看监控信息,直接使用很麻烦。springboot admin集成了actuator,可以将actuator获取到的监控信息可视化地展示出来,直观、方便。

springboot admin是codecentric公司的开源项目,并非springboot官方组件,分为server、client两部分,被监控的springboot应用作为admin client,admin server提供web界面,可查看监控信息。

大公司往往都有自己的监控组件,对于小公司而言,springboot admin可以作为应用监控的一个不错选择。

 

监控普通的springboot应用

admin server

依赖

创建项目时勾选

  • Web -> Spring Web
  • Security -> Spring Security
  • I/O -> Java Mail Sender
  • Ops -> Codecentric’s Spring Boot Admin(Server)

也可以手动添加依赖

<!-- 因为包含web界面,需要web的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 已经包含了spring-boot-starter-actuator -->
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>

<!-- 登录密码 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 非必需 -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

<!-- 邮件通知 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

 

引导类

加@EnableAdminServer

 

yml

server:
  port: 7501

spring:
  application:
    name: springboot-admin-server
    
  #指定admin server的用户名、密码
  security:
    user:
      name: chy
      password: abcd

  #邮件服务器配置
  mail:
    #邮件服务器地址。qq是smtp.qq.com,163是smtp.163.com,阿里云是smtp.aliyun.com
    host: smtp.qq.com
    #账号
    username: xxxxxx@qq.com
    #密码(授权码)
    password: xxxxxxxx

  #邮件通知配置
  boot:
    admin:
      notify:
        mail:
          #发件邮箱,与上面配置的邮箱服务器账号保持一致
          from: xxxxxxx@qq.com
          #收件邮箱,有多个时逗号分隔
          to: xxxxxxx@qq.com
          #抄送
          cc: xxxxxxx@qq.com
          #指定邮件模板,默认为 classpath:/META-INF/spring-boot-admin-server/mail/status-changed.html 可双击shift搜索此文件,copy到resources下修改
#          template:

节点上线、下线都会自动发邮件通知收件人,开发环境下屏蔽收件人设置

 

配置类

config.SecuritySecureConfig

/**
 * 配置security的登录验证
 */
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {

    private final String contextPath;

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


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 配置跨域,admin client注册到admin server的/instances下
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .ignoringAntMatchers(contextPath + "/instances");

        // 配置静态资源
        http.authorizeRequests().antMatchers(contextPath + "/assets/**").permitAll();

        // 所有请求都必须通过认证
        http.authorizeRequests().anyRequest().authenticated();

        // 登录登出的页面配置
        http.formLogin().loginPage("/login").permitAll();
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/login");

        // 启用basic认证
        http.httpBasic();
    }

    
}

 

admin client

依赖

创建项目时勾选

  • Security -> Spring Security
  • Ops -> Codecentric’s Spring Boot Admin(Client)

也可以手动添加依赖

<!-- 已经包含了spring-boot-starter-actuator -->
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>

<!-- web项目,以维持运行状态 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

 

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    
    <property name="LOG_HOME" value="C:/Users/chy/Desktop/日志"/>

    <!-- 指定彩色日志的渲染规则 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex"
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>

    <!-- 指定彩色日志的格式,LN后面是行数 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:-}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(LN:%L  ){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 引用日志格式 -->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- 每日文件输出 -->
    <appender name="DAY_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名 -->
            <FileNamePattern>${LOG_HOME}/user-server-%d{yyyy-MM-dd}.log</FileNamePattern>
            <!-- 日志文件保留天数 -->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 指定格式:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!-- 日志文件最大体积 -->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>500MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!-- 输出到指定文件中 -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${LOG_HOME}/user-server-all.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 指定格式:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- 默认输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="DAY_FILE"/>
        <appender-ref ref="FILE"/>
    </root>

    <!-- 给特殊的包指定输出级别 -->
    <logger name="com.apache.ibatis" level="WARN" />
    <logger name="java.sql.Connection" level="WARN" />
    <logger name="java.sql.Statement" level="WARN" />
    <logger name="java.sql.PreparedStatement" level="WARN" />
    <logger name="java.sql.ResultSet" level="DEBUG" />
    <logger name="com.alibaba.druid.pool.DruidPooledResultSet" level="ERROR" />

    <logger name="org.apache.shiro" level="WARN" />
    <logger name="springfox.documentation" level="WARN" />

</configuration>

注意:admin server、tail -f都可以显示彩色日志,但使用记事本之类的普通文本阅读器打开看到的是乱码。

 

yml

server:
  port: 7502

spring:
  application:
    name: user-server

  boot:
    admin:
      client:
        #指定admin server的地址
        url: http://localhost:7501
        #如果admin server设置了密码,admin client也要密码才能注册到admin server上
        username: chy
        password: abcd
        #以ip注册到admin server上,默认false使用hostname注册
        instance:
          prefer-ip: true


management:
  #暴露actuator的全部endpoint(即/actuator系列路径),默认只暴露少数endpoint
  endpoints:
    web:
      exposure:
        include: "*"
  #显示节点健康的具体信息,/actuator/health默认只返回节点状态(up|down),不返回节点的具体信息
  endpoint:
    health:
      show-details: always


#指定日志文件位置,要与logback中配置的日志文件位置一致,此处的文件名不能使用%d{yyyy-MM-dd}之类的格式,识别不了
#会把此文件中的日志传输到admin server,在admin server中也可以实时看到此应用的日志
logging:
  file:
    name: C:/Users/chy/Desktop/日志/user-server-all.log

admin server实时显示日志需要满足的条件

  • 如果没有logback的配置文件,直接在yml中logging.file.name指定日志输出位置即可
  • 如果有logback的配置文件,则yml中的logging.file.name必须和logback配置文件中指定的日志文件位置保持一致

 

监控微服务

大体流程:所有服务(包括admin server)都作为eureka client注册到eureka server上,并将状态信息传给eureka server,admin server从eureka server拿各服务的状态信息。
 

eureka server

就是一个普通的eureka server,不需要加额外的配置。
 

依赖

创建模块时勾选 Spring Cloud Discovery -> Eureka Server ,也可以手动添加依赖

<!-- 已经包含了spring-boot-starter-actuator -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

 
引导类

加 @EnableEurekaServer
 

yml

server:
  port: 7500

spring:
  application:
    name: eureka-server


eureka:
  instance:
    #所在机器的hostname或者ip
    hostname: 127.0.0.1
  client:
    #不注册到其它eureka server上
    registerWithEureka: false
    #不从其它eureka server上拉取、同步注册信息
    fetchRegistry: false
  #此eureka server绑定的注册中心地址
  serviceUrl:
    defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/


#日志文件位置
logging:
  file:
    name: C:/Users/chy/Desktop/日志/eureka-server-all.log

 

admin server

依赖

创建模块时勾选

  • Web -> Spring Web
  • Security -> Spring Security
  • I/O -> Java Mail Sender
  • Ops -> Codecentric’s Spring Boot Admin(Server)
  • Spring Cloud Discovery -> Eureka Discovery Client

也可以手动添加依赖

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

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 非必需 -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

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

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

 

引导类

加 @EnableAdminServer、@EnableEurekaClient

 

yml

server:
  port: 7501

spring:
  application:
    name: springboot-admin-server

  #指定admin server的用户名、密码
  security:
    user:
      name: chy
      password: abcd

  #邮件服务器配置
  mail:
    #邮件服务器地址。qq是smtp.qq.com,163是smtp.163.com,阿里云是smtp.aliyun.com
    host: smtp.qq.com
    #账号
    username: xxxxxxxx@qq.com
    #密码(授权码)
    password: xxxxxxxxx

  boot:
    admin:
      #配置web路径前缀,值为网关路由中配置的admin-server模块的路径,默认路由为服务名。如果不通过网关访问,可不用配置
      ui:
        public-url: /admin-server
      #邮件通知配置
      notify:
        mail:
          #发件邮箱,与上面配置的邮箱服务器账号保持一致
          from: xxxxxxx@qq.com
          #收件邮箱,有多个时逗号分隔
          to: xxxxxx@qq.com
#         #抄送
          cc: xxxxxxx@qq.com
          #邮件模板
#          template:


management:
  #暴露actuator的全部endpoint
  endpoints:
    web:
      exposure:
        include: "*"
  #显示节点健康的具体信息
  endpoint:
    health:
      show-details: always


#日志文件位置
logging:
  file:
    name: C:/Users/chy/Desktop/日志/springboot-admin-server-all.log


eureka:
  instance:
  	#默认就是/actuator/health,可缺省
    #health-check-url-path: /actuator/health
    #发送心跳包的时间间隔,默认30,开发、测试环境可设置小些
    lease-renewal-interval-in-seconds: 10
    #元数据
    metadata-map:
      user.name: ${spring.security.user.name}
      user.password: ${spring.security.user.password}
  client:
    #ribbon更新节点列表的时间间隔,默认30,开发、测试环境可设置小些
    registry-fetch-interval-seconds: 10
    #注册中心地址
    service-url:
      defaultZone: http://localhost:7500/eureka/
  • admin server是从注册中心拿各服务节点的状态信息,可以监测各个eureka client(包括 admin server本身)的状态。
  • 单机版eureka server是监测不到eureka server自身状态的,eureka server集群后,eureka server也会作为eureka client注册到其它eureka server上,这时可以监测到eureka server的状态。上面eureka server的yml中我没有暴露eureka server自身的全部端点,需要的可以自己加上。
  • 关于日志,通常不太关心eureka server、admin server自身的日志,所以我只输出到一个日志文件中,没有逐天输出,需要的可以自行加上logback-spring.xml。

 

配置类

config.SecuritySecureConfig

/**
 * 配置security的登录验证
 */
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {

    private final String contextPath;

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


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 配置跨域,admin client注册到admin server的/instances下
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .ignoringAntMatchers(contextPath + "/instances");

        // 配置静态资源
        http.authorizeRequests().antMatchers(contextPath + "/assets/**").permitAll();

        // 所有请求都必须通过认证
        http.authorizeRequests().anyRequest().authenticated();

        // 登录登出的页面配置
        http.formLogin().loginPage("/login").permitAll();
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/login");

        // 启用basic认证
        http.httpBasic();
    }

    
}

 

admin client

依赖

创建项目时勾选

  • Web -> Spring Web
  • Ops -> Codecentric’s Spring Boot Admin(Client)
  • Spring Cloud Discovery -> Eureka Discovery Client

也可以手动添加依赖

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

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<!-- 已经包含了spring-boot-starter-actuator -->
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.3.1</version>
</dependency>

admin client的依赖都是公共依赖,很多服务中已经包含了这些公共依赖,基本不用添加admin client的依赖。
 

引导类

加不加 @EnableEurekaClient 均可

 

yml

server:
  port: 7502

spring:
  application:
    name: user-server


management:
  #暴露actuator的全部endpoint
  endpoints:
    web:
      exposure:
        include: "*"
  #显示节点健康的具体信息
  endpoint:
    health:
      show-details: always


#指定日志文件位置,要与logback中配置的日志文件位置一致
logging:
  file:
    name: C:/Users/chy/Desktop/日志/user-server-all.log


eureka:
  instance:
  	#默认就是/actuator/health,可以缺省
    health-check-url-path: /actuator/health
    #发送心跳包的时间间隔,默认30,开发、测试可设置小些
    lease-renewal-interval-in-seconds: 10
  client:
    #ribbon更新节点列表的时间间隔,默认30,开发、测试环境可设置小些
    registry-fetch-interval-seconds: 10
    service-url:
      defaultZone: http://localhost:7500/eureka/

 

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">

    <property name="LOG_HOME" value="C:/Users/chy/Desktop/日志"/>

    <!-- 指定彩色日志的渲染规则 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex"
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>

    <!-- 指定彩色日志的格式,LN后面是行数 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:-}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(LN:%L  ){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 引用日志格式 -->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- 每日文件输出 -->
    <appender name="DAY_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名 -->
            <FileNamePattern>${LOG_HOME}/user-server-%d{yyyy-MM-dd}.log</FileNamePattern>
            <!-- 日志文件保留天数 -->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 指定格式:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!-- 日志文件最大体积 -->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>500MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!-- 输出到指定文件中 -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${LOG_HOME}/user-server-all.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 指定格式:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- 默认输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="DAY_FILE"/>
        <appender-ref ref="FILE"/>
    </root>

    <!-- 给特殊的包指定输出级别 -->
    <logger name="com.apache.ibatis" level="WARN" />
    <logger name="java.sql.Connection" level="WARN" />
    <logger name="java.sql.Statement" level="WARN" />
    <logger name="java.sql.PreparedStatement" level="WARN" />
    <logger name="java.sql.ResultSet" level="DEBUG" />
    <logger name="com.alibaba.druid.pool.DruidPooledResultSet" level="ERROR" />

    <logger name="org.apache.shiro" level="WARN" />
    <logger name="springfox.documentation" level="WARN" />

</configuration>

 

说明

1、像springboot admin这种第三方组件,等springboot新版本推出一段时候后才会慢慢适配,尽量不要使用很新的springboot版本。

2、@EnableAdminServer、@EnableHystrixDashboard 这2个注解有冲突,如果同时标在同一个引导类上,hystrix dashboard的静态资源会404,尽量不要在同一个模块中同时使用springboot admin、hystrix dashboard 2个监控。

3、集成spring security监控微服务这一块,应用到生产中有很多坑,不一定非要集成集成spring security,可以走内网访问。

4、有拦截器、过滤器的,要放行springboot admin的 /actuator/** 。

5、不推荐搞彩色日志这种花里花哨的东西,拉低性能。

6、需要设置日志输出等级,不然日志中会输出大量的监控信息。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值