jvisualvm の高度なバージョン: Spring Boot 管理者による Spring Boot マイクロサービス プロジェクトの監視

一緒に創造し、成長するために一緒に働きましょう!「ナゲッツデイリー新プラン・8月アップデートチャレンジ」参加30日目、イベント詳細はこちら

プレリュード: Java VisualVM について話しましょう

Java VisualVMは、 JVMを監視できるjdk に付属するグラフィカル ツールです。

image-20220828164318671.png

$JAVA_HOME/binディレクトリで、直接実行できます。

リモート サーバー上の Java プログラムを監視するには、プロジェクトの開始時にjmx起動パラメーターを追加します.spring-boot-admin-server-0.0.1-SNAPSHOT.jar事前に jar パッケージを準備し、それを Linux サーバーにアップロードし、jmx起動パラメーターを追加して起動します:

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
复制代码

jvisualvmを開くと、プログラムを監視するのは次のように簡単です。

image-20220828165434650.png

接続後、プログラムを監視でき、さまざまなインジケーターが一目でわかります。

image-20220828165532244.png

image-20220828165556502.png

単一のプロジェクトの場合、jvisualvmで監視するだけで十分です!

プレリュード: Spring Boot アクチュエータの監視

Spring BootActuatorは、独自のアプリケーション情報を監視および管理するためのモジュールです. このモジュールの使用は非常に簡単で、spring-boot-starter-actuator依存関係です:

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

SpringCloudAlibabaDemoproject の下にサブプロジェクトを作成しspring-boot-admin-server、上記の依存関係を導入してから、プロジェクトを開始して以下にアクセスしますhttp://localhost:8082/actuator

image-20220828154513357.png

初期設定でアクチュエータにアクセスした場合の情報です。

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
复制代码

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

小结:为啥要监控?

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

ただし、通常の作業では、OOM のトラブルシューティングプロジェクト パラメーターの調整など、実際に問題が発生した場合は、次のことを行う場合があります。

  • 単一プロジェクトの場合は、JDKに付属のjvisualvm監視ツールを使用してプロジェクトを監視し、スレッド数やスレッドの実行時間など、インストールされているクラスの数を確認することで、どのクラスが通過しているかを簡単に見つけることができます。クラスは多くのメモリを占有し、特定の問題を特定します。
  • 複数のプロジェクトがある場合は、 Spring Boot Adminなどのツールを使用してマイクロサービス プロジェクトを監視し、レジストリ (Nacos など) に登録されているすべてのサービスの状態を確認して、特定の問題を分析できます。

問題をトラブルシューティングして解決するには、プログラムを最適化するために監視が必要です。

おすすめ

転載: juejin.im/post/7137095477526265863