Advanced version of jvisualvm: Spring Boot Admin monitoring Spring Boot microservice projects

Work together to create and grow together! This is the 30th day of my participation in the "Nuggets Daily New Plan·August Update Challenge", click to view the details of the event

Prelude: Let's talk about Java VisualVM

Java VisualVM is a graphical tool that comes with jdk that can monitor the JVM :

image-20220828164318671.png

In the $JAVA_HOME/bindirectory , you can run it directly.

To monitor the Java program on the remote server, you can add jmx startup parameters when starting the project. I prepared a spring-boot-admin-server-0.0.1-SNAPSHOT.jarjar package in advance, uploaded it to my Linux server, and added jmx startup parameters to start it:

java -jar -Djava.rmi.server.hostname=192.168.242.112 -Dcom.sun.management.jmxremote.port=1888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false spring-boot-admin-server-0.0.1-SNAPSHOT.jar
复制代码

Now open jvisualvm and monitoring the program is as simple as:

image-20220828165434650.png

After connecting, you can monitor the program, and various indicators are at a glance:

image-20220828165532244.png

image-20220828165556502.png

For a single project, monitoring with jvisualvm is enough!

Prelude: Spring Boot Actuator Monitoring

Spring Boot 's Actuator is a module for monitoring and managing its own application information. Using this module is very simple, just add spring-boot-starter-actuatordependencies :

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

SpringCloudAlibabaDemoWe create a sub-project under the project spring-boot-admin-server, introduce the above dependencies, then start the project and visit: http://localhost:8082/actuator:

image-20220828154513357.png

This is the information when accessing the Actuator under the default configuration .

Actuator 端点(Endpoints)可以监视应用程序并与之交互。 Spring Boot 包含许多内置端点,并允许添加自己的端点。例如,health 端点提供基本的应用程序健康信息。

每个单独的端点都可以通过 HTTP 或 JMX 启用或禁用和远程访问。大多数应用程序选择通过 HTTP 对外暴露信息,访问端点的 URL 由 /actuator 前缀以及端点的 ID 组成。例如,默认情况下,health 端点映射到 /actuator/health ,即查看应用程序的健康状况可以访问 URL http://localhost:8082/actuator/health

image-20220828155556190.png

返回信息:

{
    "status": "UP"
}
复制代码

UP 表示当前应用处于健康状态,如果是 DOWN 则表示不健康,增加 management.endpoints.health.show-details=ALWAYS 可以查看应用健康状况的详细信息:

management:
  endpoint:
    health:
      show-details: always
复制代码

image-20220828162539633.png

Actuator 提供了很多端点信息,如下所示:

HTTP方法 端点路径 含义 是否默认暴露
GET /actuator/configprops 显示所有 @ConfigurationProperties 的配置列表。 false
GET /actuator/beans 查看 Bean 及其关系列表 false
GET /actuator/heapdump 下载堆栈信息 false
GET /actuator/env 查看所有环境变量 false
GET /actuator/health 查看应用的健康指标 true
GET /actuator/info 查看应用信息 false
GET /actuator/mappings 查看所有 URL 映射 false
GET /actuator/httptrace 追踪信息 false
GET /actuator/loggers loggers 配置 false
GET /actuator/scheduledtasks 显示定时任务 false
GET /actuator/threaddump 显示线程信息 false
GET /actuator/sessions 允许从 Spring Session 支持的会话存储中检索和删除用户会话 false

完整列表见 Spring 官网:docs.spring.io/spring-boot… 。注意选择的 Spring Boot 版本信息。

从这个表可以看出,大部分的端点默认是不暴露的,我们可以通过如下配置进行合理的端点暴露(多个用逗号分开):

management:
  endpoints:
    web:
      exposure:
        include: beans,threaddump
复制代码

暴露全部的话,直接进行如下配置即可:

management:
  endpoints:
    web:
      exposure:
        include: '*'
复制代码

当然,我们也可以扩展 actuator 端点,拿 health 端点为例,我们先看一下其返回的结果:

{
    "status": "UP",
    "components": {
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 18238930944,
                "free": 11510571008,
                "threshold": 10485760,
                "exists": true
            }
        },
        "ping": {
            "status": "UP"
        }
    }
}
复制代码

可以看到,返回结果中有 components 下的 diskSpace ,我们从 spring-boot-actuator 源码中找到该返回结果的定义,在 spring-boot-actuator 中搜 diskSpace 关键字:

image-20220828170644769.png

进入 DiskSpaceHealthIndicator 类:

image-20220828171018416.png

可以看到该类继承 AbstractHealthIndicator 类,并在 doHealthCheck() 方法中定义了返回详情,那么我们自定义一个自己的健康检查类,输出自定义的信息的话,我们也创建一个 Component ,让他继承 AbstractHealthIndicator 实现输出自定义的信息。

/**
 * 博客:https://chendapeng.cn - 行百里者半九十,凡是善始善终,吾将上下而求索!
 * 公众号:行百里er
 *
 * @author 行百里者
 * @date 2022-08-28 17:13
 */
@Component
public class ChenDapengHealthIndicator extends AbstractHealthIndicator {

    /**
     * 自定义健康检查输出信息
     */
    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        builder.up()
                .withDetail("status", "Oj8K!")
                .withDetail("whoami", "外星人")
                .withDetail("uptime", new Date());
    }
}

复制代码

再次访问健康状况,结果如下:

image-20220828171936525.png

高潮:Spring Boot Admin

有了 Actuator 的监控信息,我们总不能每次都站在干岸上看那些无聊的 JSON 数据吧?当然不能委屈自己,目下就有一个能够将 Actuator 的信息进行图形化展示的监控管理软件,没错,他就是 Spring Boot Admin

更让人兴奋的是,Spring Boot Admin 还能监控注册中心中的所有微服务的情况,并且还提供实时警报功能,这个使用 jvisualvm 就没办法搞了。

Spring Boot Admin 是一个开源项目,项目地址:github.com/codecentric…

创建 Spring Boot Admin Server

Spring Boot Admin 分为 Server 端和 Client 端。

Server 端引入 spring-boot-admin-starter-server 的依赖:

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
    <version>2.5.1</version>
</dependency>
复制代码

并且在启动类上加 @EnableAdminServer 注解:

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

启动项目后,输入 http://localhost:8082/ 访问:

image-20220828174535440.png

这样一个 admin server 就起来了。

将微服务注册到 Spring Boot Admin

Spring Boot Admin 怎么去监控服务呢,得有服务注册到 Admin Server 上来才行,所以我们将之前的几个微服务注册进来。

需要注册到 Admin Server 上的服务我们暂且称之为客户端,那么客户端需要怎么做呢?

1, 每个需要注册到 Admin Server 的服务都引入如下依赖:

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

2, 配置连接到 Admin Server 的 url :

spring:
  boot:
    admin:
      client:
        url: http://localhost:8082
复制代码

3, 配置对外暴露所有 Actuator 端点:

management:
  endpoints:
    web:
      exposure:
        include: '*'
复制代码

启动服务:

image-20220828183431176.png

然后看监控:

image-20220828183509057.png

what!竟然全部灰色,意思是全部离线,可是我的所有服务都正常启动了啊,点进去看一下:

image-20220828184338625.png

看这个提示,应该能明白的差不多了,应该需要我们把应用的 url 在 admin 中显示为 ip 地址应该就可以了,果然有这个配置:

spring:
  boot:
    admin:
      client:
        url: http://localhost:8082
        # 注册时 admin 中显示IP地址不显示主机名
        prefer-ip: true
复制代码

然后再重启:

image-20220828184926914.png

舒服了,全部在线!找一个服务点进去看细节:

image-20220828185025897.png

这个图是不是似曾相识啊!

没错,这个如就是和前面我们提到的 jvisualvm 的监控界面差不多,都有对 进程线程垃圾回收内存 等的监控,还有 JVM 各种指标的监控,想要康的东西应有尽有!

开启 Spring Boot Admin 认证

Spring Boot Admin 服务很有可能需要在外网访问,不可能让所有人输入一个网址就能随随便便看到我们服务的信息,因此需要登录功能。

Spring Boot Admin 官方说,由于有多种方法可以解决分布式 Web 应用程序中的身份验证和授权,因此 Spring Boot Admin 没有提供默认方法。我们借助于 spring-boot-starter-security 就可以实现开启登录认证功能。

1, 引入依赖:

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

2,application.yml 配置文件中配置:

spring:
  security:
    user:
      name: admin
      password: admin123
复制代码

3, 自定义安全配置类:

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    private final AdminServerProperties adminServer;

    private final SecurityProperties security;

    public MySecurityConfig(AdminServerProperties adminServer, SecurityProperties security) {
        this.adminServer = adminServer;
        this.security = security;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(this.adminServer.path("/"));

        http.authorizeRequests(
                (authorizeRequests) -> authorizeRequests.antMatchers(this.adminServer.path("/assets/**")).permitAll()
                        .antMatchers(this.adminServer.path("/actuator/info")).permitAll()
                        .antMatchers(this.adminServer.path("/actuator/health")).permitAll()
                        .antMatchers(this.adminServer.path("/login")).permitAll().anyRequest().authenticated()
        ).formLogin(
                (formLogin) -> formLogin.loginPage(this.adminServer.path("/login")).successHandler(successHandler).and()
        ).logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout"))).httpBasic(Customizer.withDefaults())
                .csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                        .ignoringRequestMatchers(
                                new AntPathRequestMatcher(this.adminServer.path("/instances"),
                                        HttpMethod.POST.toString()),
                                new AntPathRequestMatcher(this.adminServer.path("/instances/*"),
                                        HttpMethod.DELETE.toString()),
                                new AntPathRequestMatcher(this.adminServer.path("/actuator/**"))
                        ))
                .rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
    }

    // Required to provide UserDetailsService for "remember functionality"
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser(security.getUser().getName())
                .password("{noop}" + security.getUser().getPassword()).roles("USER");
    }
}
复制代码

该配置类是 Spring Boot Admin 官网提供的:codecentric.github.io/spring-boot…

再次访问 admin 的时候,就需要登录了:

image-20220828191056379.png

最后,需要注意的是,既然 admin server 开启了登录认证,那么向 server 中注册的服务也必须得提供用户名密码才能注册上去,在客户端添加如下配置即可:

spring.boot.admin.client:
   username: admin
   password: admin123
复制代码

集成 Nacos 进行服务发现

不知道大家发现了没有,我们要想让 Admin Server 监控我们的微服务,所有的微服务都得引入 admin 的相关依赖并且都得配置 admin server 的地址,用户名,密码等。这样太繁琐了!

其实我们可以将 admin server 也注册到 Nacos 注册中心,然后 admin server 自动从 Nacos 中获取服务信息来统一查看。

在 admin server 中引入 nacos 依赖,以及配置注册中心地址:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
复制代码
sping:
    cloud:
        nacos:
          discovery:
            # Nacos 集群
            server-addr: 192.168.242.112:81
复制代码

这样就不用每个客户端都要写一大堆的配置了!

小结:为啥要监控?

因为面试官可能会问:“你平时是怎么调优的?” 呵呵,当然不是。

However, in our usual work, when we really encounter problems such as OOM troubleshooting and project parameter tuning , we may do the following:

  • If it is a single project, use the jvisualvm monitoring tool that comes with the JDK to monitor the project. By checking how many classes are installed, including how many threads and the running time of the threads, you can easily find which one is through the graphical interface and easily. Classes take up a lot of memory, and then locate specific problems.
  • If there are multiple projects, we can monitor the microservice project through tools such as Spring Boot Admin , you can see the status of all services registered in the registry (such as Nacos), and then analyze the specific problems.

In order to troubleshoot and solve problems, in order to optimize the program, we need monitoring.

Guess you like

Origin juejin.im/post/7137095477526265863