51好读  ›  专栏  ›  码农小胖哥

Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

码农小胖哥  · 掘金  ·  · 2019-10-20 03:57

正文

阅读 10

Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

sbalogo.png

1. 前言

生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以通过一个轻量级的监控工具 Spring Boot Admin (SBA) 来进行监控。

2. Spring Boot Admin

Spring Boot Admin 是由德国软件工程师 Johannes Edmeier 开源的用于管理和监控 Spring Boot 应用程序。已经被收纳入 Spring Initializr 截至发文时间的最新正式版本为 2.1.6 ,快照为 2.2.0-SNAPSHOT C/S 架构风格 。 应用程序作为 Spring Boot Admin Client Spring Boot Admin Server 注册(通过 HTTP )或使用 Spring Cloud 注册中心(如 Eureka Consul )发现。SERVER程序采用了 响应式Web框架 Spring Webflux 。 展示UI采用了 Vue.js ,展示Spring Boot Admin Client 通过 Spring Boot Actuator 端点上的一些监控。常见的功能或者监控如下:

  • 显示健康状况
  • 显示应用度量指标详情,例如
    • JVM和内存指标
    • micrometer 度量
    • 数据源指标
    • 缓存指标
  • 显示构建信息编号
  • 关注并下载日志文件
  • 下载 heapdump
  • 查看 jvm 系统和环境属性
  • 查看 Spring Boot 配置属性
  • 支持 Spring Cloud 的环境端点和刷新端点
  • 支持 K8s
  • 易用的日志级别管理
  • JMX-beans 交互
  • 查看线程转储
  • 查看 http 跟踪
  • 查看 auditevents
  • 查看 http-endpoints
  • 查看计划任务
  • 查看和删除活动会话(使用 Spring Session
  • 查看 Flyway / Liquibase 数据库迁移
  • 状态变更通知(通过电子邮件,Slack,Hipchat等,支持钉钉)
  • 状态更改的事件日志(非持久化)

3. 快速集成

接下来让我们来在 Spring Boot 项目中集成 Spring Boot Admin 。注意版本的兼容性,可通过 Spring Initializr 来验证。

3.1 配置 Spring Boot Admin Server

Spring Boot Admin Server 一般推荐独立作为一个 Spring Boot jar 应用运行。 只需要将下列依赖添加到你的 pom.xml 中:

  <dependency>
      <groupId>de.codecentric</groupId>
      <artifactId>spring-boot-admin-starter-server</artifactId>
      <version>2.2.0-SNAPSHOT</version>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
 <!-- 生产需要保证监控的安全性-->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
  </dependency>复制代码

然后通过添加 @EnableAdminServer 到配置中来引入 Spring Boot Admin Server 配置:

  @EnableAdminServer
  @SpringBootApplication
  public class SpringBootAdminApplication {
      public static void main(String[] args) {
          SpringApplication.run(SpringBootAdminApplication.class, args);
      }
  }复制代码

3.2 配置 Spring Boot Admin

每个要注册的应用程序都必须包括 Spring Boot Admin Client 。为了保护端点,你还应该添加安全依赖 spring-boot-starter-security

  <dependency>
      <groupId>de.codecentric</groupId>
      <artifactId>spring-boot-admin-starter-client</artifactId>
      <version>2.2.0-SNAPSHOT</version>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
  </dependency>复制代码

然后在客户端应用程序的 application.yml 中增加以下配置:

   spring:
      boot:
        admin:
          client:
      # Spring Boot Admin Server 地址   http://localhost:8080  可自定义 
              url:  http://localhost:8080 
      # 默认情况下,大多数端点都不通过http公开,我们公开了所有端点。对于生产,您应该仔细选择要公开的端点。
   management:
     endpoints:
       web:
         exposure:
           include: '*'
     endpoint:
         health:
           show-details: ALWAYS复制代码

分别启动 SBA 服务端和客户端 。打开服务端页面 http://localhost:8080 将进入以下监控界面:

wallboard

进而也可以获取 admin-client 的具体监控指标:

detail.png

如果您已经将 Spring Cloud Discovery ( eureka consul 等)用于您的应用程序,则不需要 Spring Boot Admin 客户端。只需将 DiscoveryClient 添加到 Spring Boot Admin Server ,其余的事情通过自动配置完成,可通过官方示例来查看。

4. Spring Boot Admin 安全访问控制

应用的监控指标都是极其敏感的数据。所以生产上必须增加安全访问控制以避免发生泄漏事件。你可以使用你擅长的安全框架来做访问控制。这里我们采用 Spring Security 来保护我们的 Spring Boot Admin

4.1 保护 Spring Boot Admin Server 服务器

添加 Spring Security Starter 依赖:

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
  </dependency>复制代码

设置管理账户信息

   spring:
     security:
       user:
         name: SBA_admin
         password: SBA_password
         roles: SBA_ADMIN复制代码

配置安全路径访问控制

  package cn.felord.admin.server.configuer;
  
  import de.codecentric.boot.admin.server.config.AdminServerProperties;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.http.HttpMethod;
  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 org.springframework.security.web.util.matcher.AntPathRequestMatcher;
  
  import java.util.UUID;
  
  /**
   * The type Security secure config.
   *
   * @author Felordcn
   * @since 2019 /10/19 23:33
   */
  @Configuration
  public class AdminServerSecurityConfig extends WebSecurityConfigurerAdapter {
      private final AdminServerProperties adminServer;
  
      /**
       * Instantiates a new Security secure config.
       *
       * @param adminServer the admin server
       */
      public AdminServerSecurityConfig(AdminServerProperties adminServer) {
          this.adminServer = adminServer;
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          // @formatter:off
          SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
          successHandler.setTargetUrlParameter("redirectTo");
          final String adminServerContextPath = this.adminServer.getContextPath();
          successHandler.setDefaultTargetUrl(adminServerContextPath+"/");
  
          http.authorizeRequests()
                  .antMatchers(adminServerContextPath + "/assets/**").permitAll() // <1>
                  .antMatchers(adminServerContextPath + "/login").permitAll()
                  .anyRequest().authenticated() // <2>
                  .and()
                  .formLogin().loginPage(adminServerContextPath + "/login").successHandler(successHandler).and() // <3>
                  .logout().logoutUrl(adminServerContextPath + "/logout").and()
                  .httpBasic().and() // <4>
                  .csrf()
                  .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // <5>
                  .ignoringRequestMatchers(
                          new AntPathRequestMatcher(adminServerContextPath + "/instances", HttpMethod.POST.toString()),  // <6>
                          new AntPathRequestMatcher(adminServerContextPath + "/instances/*", HttpMethod.DELETE.toString()),  // <6>
                          new AntPathRequestMatcher(adminServerContextPath + "/actuator/**")  // <7>
                  )
                  .and()
                  .rememberMe().key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600);
  
      }
  
  }复制代码






请到「今天看啥」查看全文