SpringBoot - 运行性能监控

发布于 2024-11-10 07:17:00 字数 18265 浏览 5 评论 0

前言

方式一: Spring Boot Actuator + Micrometer + Prometheus + Grafana

方式二: Spring Boot Actuator + Spring Boot Admin

方式一 Micrometer + Prometheus + Grafana

pom.xml

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>io.micrometer</groupId>
  <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

如果使用了 Spring Security 等权限框架需要放开

web.ignoring().antMatchers("/actuator", "/actuator/**");
management:
  endpoints:
    web:
      exposure:
        include: 'prometheus'
  metrics:
    tags:
      application: ${spring.application.name}

浏览器测试

http://localhost:8080/actuator/prometheus 

Prometheus

Prometheus 是一款开源的监控 + 时序数据库 + 报警软件

Prometheus 官网 下载,或者访问 docker 进行安装

docker pull prom/statsd-exporter

docker run -d -p 9090:9090 \
    -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus --config.file=/etc/prometheus/prometheus.yml

需编写 prometheus.yml

新增

scrape_configs:
- job_name: 'springboot'
  scrape_interval: 15s
  scrape_timeout: 10s
  metrics_path: '/actuator/prometheus'
  static_configs:
  - targets: ['localhost:8080']

如果不是采用的 docker 方式,直接找到安装目录下的 prometheus.yml,在 scrape_configs 新增

scrape_configs:
  - job_name: 'springboot'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.
    metrics_path: '/actuator/prometheus'
    static_configs:
    - targets: ['localhost:8080']

targets 对应需要监控的服务地址

浏览器访问测试

http://localhost:9090 

至此,已经用 Prometheus 实现了监控数据的可视化,然而使用体验并不好。下面来用 Grafana 实现更友好、更贴近生产的监控可视化。

grafana

Grafana 是一个开源的跨平台度量分析和可视化 + 告警工具

grafana

使用 docker 安装

docker run -d --name=grafana -p 3000:3000 grafana/grafana

Windows 的话下载 zip 或者安装包直接安装即可

登录:访问 http://localhost:3000 ,初始账号/密码为:admin/admin

grafana-home

绑定 Prometheus

左侧菜单选择 Configuration-datasources-Add data source

添加 Prometheus 地址

grafana-add-proetheus

点击 save&test,测试成功即可

创建监控 Dashboard

左侧菜单选择+Create-Import,输入 id 为 4701 ,这个是为 Micrometer 提供的增强包。有兴趣可以前往 Grafana Lab - Dashboards ,输入关键词即可搜索指定 Dashboard, 详情页的右上角找到 id

grafana-dashboard-id

比较好用的 Dashboard

  • JVM (Micrometer)
  • JVM (Actuator)
  • Spring Boot Statistic

注意是以 Prometheus 作为数据源,支持 Micrometer 的 Dashboard

grafana-import

点击右侧 load 后,选择 prometheus,确认后 import

grafana-import-select-prometheus

如果选择项是空的,注意是否开启了 prometheus

grafana-dashboard

可查看监控的服务 jvm 等情况

告警

Grafana 支持的告警渠道非常丰富,例如邮件、钉钉、Slack、Webhook 等,有兴趣可以了解下

方式二 Spring Boot Admin

Spring Boot Admin 是一个开源社区项目,用于管理和监控 SpringBoot 应用程序。 应用程序作为 Spring Boot Admin Client 向为 Spring Boot Admin Server 注册(通过 HTTP)或使用 SpringCloud 注册中心(例如 Eureka,Consul)发现。 UI 是的 AngularJs 应用程序,展示 Spring Boot Admin Client 的 Actuator 端点上的一些监控。

搭建

创建两个 SpringBoot 项目,一个作为监控端(admin-server-demo),一个作为被监控端(admin-client-demo)

server 端

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.jonesun</groupId>
	<artifactId>admindemo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>admin-server-demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>14</java.version>
		<spring-boot-admin.version>2.3.1</spring-boot-admin.version>
	</properties>

	<dependencies>
		<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-mail</artifactId>
        </dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>de.codecentric</groupId>
				<artifactId>spring-boot-admin-dependencies</artifactId>
				<version>${spring-boot-admin.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

application.yml

server:
  port: 8001
spring:
  application:
    name: admin-server
  boot:
    admin:
      notify:
        mail:
          # 收件人列表(多个使用,分隔)
          to: xxx@163.com
          # 是否开启(如果暂时不需要通知,可关闭)
          enabled: true
          # 抄送
          cc: 111@163.com,222@163.com
          # 发件人
          from: xxx<aaa@163.com>

  mail:
    host: smtp.163.com
    # port: 25
    username: aaa@163.com
    default-encoding: utf-8
    password: xxxxxx

QQ、163 等邮箱需要设置授权码,password 填生成好的授权码,如果不需要邮件告警,去除 mail 相关配置即可

AdminServerDemoApplication.java

@EnableAdminServer
@SpringBootApplication
public class AdminServerDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(AdminServerDemoApplication.class, args);
	}

}

注意,一定要加上 @EnableAdminServer

client 端

新建 Spring Boot 项目

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.jonesun</groupId>
	<artifactId>admin-client-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>admin-client-demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>14</java.version>
		<spring-boot-admin.version>2.3.1</spring-boot-admin.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<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>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>de.codecentric</groupId>
				<artifactId>spring-boot-admin-dependencies</artifactId>
				<version>${spring-boot-admin.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

application.yml

spring:
  application:
    name: admin-client
  boot:
    admin:
      client:
        url: http://localhost:8001 
        instance:
          # 客户端实例 url
          service-url: http://127.0.0.1:8002 
          prefer-ip: true
          # 客户端实例名称
          name: cts-vivo-preview
server:
  port: 8002

management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: ALWAYS

运行验证

分别启动两个服务,然后浏览器中打开 server 端的网址: http://localhost:8001/

即可查看监控信息,和服务的详细情况

springboot-admin

如果存在 Spring Security,则需要添加自定义安全配置,以允许对端点进行未经身份验证的访问

@Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests()
            .anyRequest().permitAll()
    }

}

查看日志

如果想在 admin-server 中查看 client 的日志,则需在 client 的 application.yml 中加入配置:

logging:
  pattern:
    file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"
  file:
    # 日志所在路径(需与日志框架中配置的路径一致)
    name: C:/tmp/admin-client/spring-log.log

注意 logging.file.name 不支持表达式,所以项目中无论是使用默认 logback 还是 log4j2,都需要匹配好日志路径及名称。如果需要配置相对路径则可配置为./log/xxx.log,表示为项目所在目录下的 log 文件夹中的 xxx.log 文件 低版本的 springBoot 没有 logging.file.name,可直接配置为 logging.file

这样就可以在 admin-server 中查看日志,无需登录到服务器上查看了,甚至可以利用日志配置,在线实时调整日志的显示级别(内部原理也是 actuator),方便在出现异常情况下查看详细的日志打印

spring-boot-admin-log

spring-boot-admin-log-config

告警

结合 spring-boot-starter-mail(admin-server 中配置) 进行告警,主要是 Spring Boot Actuator 的使用,这里举个例子:

当服务器中的磁盘容量不足 5GB 时,进行邮件告警

修改 client-server 中的 application.yml

management:
  endpoints:
    web:
      exposure:
        include: '*'
        exclude: env,beans
    jmx:
      exposure:
        include: health,info
  endpoint:
    health:
      show-details: ALWAYS
  health:
    diskspace:
      # 当磁盘容量不足 5GB 时告警
      threshold: 5GB

实际项目中肯定不能将所有 endpoint 都暴露,根据项目自己调整

这边我们设置 diskspace 的阈值为 5GB, 即如果运行环境的磁盘容量不足 5GB 时进行告警(本地测试的话为看到邮件通知可调整为较大的数值如 150GB)

重新启动项目后, 就会收到邮件通知,并且 admin-server 中对应的 diskspace 状态会为 DOWN

权限验证

当使用 Spring Boot Actuator 和 Spring Boot Admin, 实际项目中肯定不能直接暴露到让人随意访问,这里我们加入 Spring Security

  • admin-server 中

pom.xml 中加入

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

application.yml 中加入测试账户(实际项目中可结合数据库进行配合),不过一般项目写死也可以,毕竟服务器配置一般不会外传

spring:
  security:
    user:
      name: admin
      password: admin123

加入权限配置 SecurityConfig:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final String contextPath;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 跨域设置,SpringBootAdmin 客户端通过 instances 注册,见 InstancesController
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .ignoringAntMatchers(contextPath + "/instances");

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

        http.formLogin().loginPage("/login").permitAll();
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/login");

        // 启用 basic 认证,SpringBootAdmin 客户端使用的是 basic 认证
        http.httpBasic();
    }
}

  • client-server 中

application.yml 中加入配置

spring:
  boot:
    admin:
      client:
        username: admin
        password: admin123

分别重启两个项目,浏览器访问 admin-server,可以发现需要登录才可以查看

spring-boot-admin-login

如果 client-server 也使用了 security

则首先需支持 HTTP BASIC 方式访问端点(默认是支持的),然后将元数据提供给 admin-server

client-server 中 application.yml 加入:

spring:
   boot:
     admin:
       client:
         instance:
           metadata:
             user.name: ${spring.security.user.name}
             user.password: ${spring.security.user.password} 

如果不支持的话,则可以定制 HttpHeadersProvider 来达到效果

示例源码

Spring Cloud 下的应用

集成了 Spring Cloud Discovery (如 eureka) 到应用程序后,则不需要 Spring Boot Admin 客户端。 只需在 DiscoveryClient 中添加 Spring Boot Admin Server,其他新增应用的话直接注册到 DiscoveryServer 即可。

示例源码

与 Spring Boot Admin 类似的还有 Apache Skywalking 利用的 java agent, 可以监控任意的 java 应用,感兴趣可以了解下

常见问题

  • 监控页面对应信息一栏显示: 未提供任何信息,需要使用 spring-boot 的插件,运行 spring-boot:build-info,生成 Actuator 使用的构建信息文件 build-info.properties, 再次运行就可以看到了

spring-boot-admin-info

或者在 application.yml 中加入:

info:
  version: @project.version@
  name: @project.artifactId@
  group: @project.groupId@
  description: @project.description@
  #还可以自定义信息
  author: jone sun
  blog: https://jonesun.github.io/ 

如果运行后出现类似:

org.yaml.snakeyaml.scanner.ScannerException: while scanning for the next token
found character '@' that cannot start any token. (Do not use @ for indentation)
 in 'reader', line 39, column 12:
      version: @project.version@

错误,先检查下 pom.xml 中是否存在对应值,尤其有些项目没有写 description,再在 build 标签下新增:

 <resources>
    <resource>
        <directory>src/main/resources</directory>
        <!--开启过滤,用指定的参数替换 directory 下的文件中的参数-->
        <filtering>true</filtering>
    </resource>
</resources>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

笔芯

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

玍銹的英雄夢

文章 0 评论 0

我不会写诗

文章 0 评论 0

十六岁半

文章 0 评论 0

浸婚纱

文章 0 评论 0

qq_kJ6XkX

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文