首页 > 其他分享 >SpringBoot Actuator监控

SpringBoot Actuator监控

时间:2022-12-18 15:12:32浏览次数:55  
标签:http SpringBoot tomcat import 监控 actuator Actuator localhost 8081

Actuator帮助我们监控和管理Spring Boot 应用。

1. 集成Actuator

1.1 build.gradle

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: springBootVersion
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: springBootVersion

1.2  applicaiton.properties

management.security.enabled=false
management.endpoints.web.exposure.include=*
management.endpoint.health.showDetails=always

1.3 代码

1.3.1 actuator代码

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.info.InfoEndpoint;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@Order(1)
class ActuatorWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/actuator/**")
                .authorizeRequests() // NOSONAR
                .requestMatchers(EndpointRequest.to(HealthEndpoint.class, InfoEndpoint.class))
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin();
    }
}

 

1.3.2 actuator集成mongo监控代码(监控多个mongo clusters)

自定义健康监控:CustomHealthIndicator
package com.test.ark.mls.actuator;

import com.test.ark.mls.config.PrimaryMongoConfig;
import com.test.ark.mls.config.SecondaryMongoConfig;
import com.mongodb.client.MongoDatabase;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class CustomHealthIndicator extends AbstractHealthIndicator {
  @Autowired private PrimaryMongoConfig primaryMongoConfig;
  @Autowired private SecondaryMongoConfig secondaryMongoConfig;
  @Autowired
  @Qualifier(value="primaryMongoTemplate")
  private MongoTemplate primaryMongoTemplate;
  @Autowired
  @Qualifier(value="secondMongoTemplate")
  private MongoTemplate secondMongoTemplate;

  public CustomHealthIndicator(PrimaryMongoConfig primaryMongoConfig) {
    this.primaryMongoConfig = primaryMongoConfig;
  }

  @Override
  protected void doHealthCheck(Health.Builder builder) throws Exception {
    MongoDatabase database = primaryMongoTemplate.getDb();
    Document doc = new Document();
    doc.append("dbStats", 1);
    doc.append("scale", 1);
    Document collStatsResults = database.runCommand(doc);
    JSONObject jsonValue = new JSONObject(collStatsResults.toJson());
    MongoDatabase database2 = secondMongoTemplate.getDb();
    Document doc2 = new Document();
    doc2.append("dbStats", 1);
    doc2.append("scale", 1);
    Document collStatsResults2 = database2.runCommand(doc2);
    JSONObject jsonValue2 = new JSONObject(collStatsResults2.toJson());
    builder
        .up()
        .withDetail(
            "PrimaryMongoAddress",
            primaryMongoConfig.getUri())
        .withDetail("PrimaryMongoStats", jsonValue.toString())
        .withDetail(
            "SecondMongoAddress",
                secondaryMongoConfig.getUri())
            .withDetail("SecondMongoStats", jsonValue2.toString());
  }
}

 

PrimaryMongoConfig
@Configuration
@Data
@Immutable
@EqualsAndHashCode(callSuper = false)
@Slf4j
public class PrimaryMongoConfig extends AbstractMongoConfig {
  @Value("${spring.data.mongodb.database}")
  private String database;
  @Value("${spring.data.mongodb.uri}")
  private String uri;

  @Autowired
  private CyberarkUtil cyberarkUtil;
  @Primary
  @Override
  @Bean(name="primaryMongoTemplate")
  public MongoTemplate getMongoTemplate() throws Exception {
    String newUri = uri.replace("password", cyberarkUtil.retrievePassword());
    return new MongoTemplate(mongoDatabaseFactory(newUri, database));
  }

  public boolean pingPrimaryMongo(MongoTemplate mongoTemplate) {
    try {
      mongoTemplate.find(new Query(), Map.class);
      log.info("ping mongo success");
      return true;
    } catch (Exception e) {
      log.error("ping mongo with error: ", e);
      return false;
    }
  }

  @Bean
  public GridFsTemplate gridFsTemplate(MappingMongoConverter mappingMongoConverter)
          throws Exception {
    String newUri = uri.replace("password", cyberarkUtil.retrievePassword());
    return new GridFsTemplate(mongoDatabaseFactory(newUri, database), mappingMongoConverter);
  }
}
SecondMongoConfig
@Configuration
@Data
@Immutable
@EqualsAndHashCode(callSuper = false)
@Slf4j
public class SecondaryMongoConfig extends AbstractMongoConfig {

  @Value("${spring.data.mongodb.database2}")
  private String database;

  @Value("${spring.data.mongodb.uri2}")
  private String uri;

  @Value("${spring.data.mongodb.password2}")
  private String password;

  @Override
  @Bean(name = "secondMongoTemplate")
  public MongoTemplate getMongoTemplate() throws Exception {
    String newUri = uri.replace("password", password);
    return new MongoTemplate(mongoDatabaseFactory(newUri, database));
  }
}

 

 AbstractMongoConfig
import com.mongodb.ConnectionString;
import com.mongodb.client.MongoClients;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;

public abstract class AbstractMongoConfig {

    public MongoDatabaseFactory mongoDatabaseFactory(String uri, String database) throws Exception {
        ConnectionString connectionString = new ConnectionString(uri);
        return new SimpleMongoClientDatabaseFactory(MongoClients.create(connectionString), database);
    }

    public abstract MongoTemplate getMongoTemplate() throws Exception;
}

MongoDB properties

spring.data.mongodb.uri=mongodb://FID1:password1@mongoHost1:port1/?replicaSet=MGORPST_3004&ssl=true&sslInvalidHostNameAllowed=true
spring.data.mongodb.uri2=mongodb://FID2:password2@mongoHost2:port2/marketdata?ssl=true&authSource=admin
spring.data.mongodb.database1=test1
spring.data.mongodb.database2=test2

management.security.enabled=false //不启用登录actuator页面验证

management.endpoints.web.exposure.include=*  //放开所有endpoint(不包含shutdown),如果management.endpoints.web.exposure.include=beans,mappings之放开actuator/beans和actuator/mappings

management.endpoint.health.showDetails=always

 

 

调用 http://localhost:8081/actuator/health结果

{
    "status": "UP",
    "components": {
        "custom": {
            "status": "UP",
            "details": {
                "PrimaryMongoAddress": "mongodb://FID:password@host:port/?replicaSet=MGORPST_3004&ssl=true&sslInvalidHostNameAllowed=true",
                "PrimaryMongoStats": "{\"objects\":178082860,\"scaleFactor\":1,\"dataSize\":534560218484,\"indexSize\":13836587008,\"operationTime\":{\"$timestamp\":{\"t\":1671342061,\"i\":5}},\"totalSize\":378842005504,\"$clusterTime\":{\"clusterTime\":{\"$timestamp\":{\"t\":1671342061,\"i\":5}},\"signature\":{\"keyId\":7129165744469704705,\"hash\":{\"$binary\":{\"base64\":\"DlyyV0xsnvCfsDtJ0j\\/0zEdH9XI=\",\"subType\":\"00\"}}}},\"indexes\":388,\"collections\":102,\"storageSize\":365005418496,\"fsUsedSize\":716543451136,\"avgObjSize\":3001.7499633822144,\"ok\":1,\"db\":\"test\",\"views\":0,\"fsTotalSize\":951036878848}",
                "SecondMongoAddress": "mongodb://FID:password@host:port/marketdata?ssl=true&authSource=admin",
                "SecondMongoStats": "{\"objects\":131977,\"scaleFactor\":1,\"dataSize\":312007082,\"indexSize\":13578240,\"operationTime\":{\"$timestamp\":{\"t\":1671342063,\"i\":1}},\"totalSize\":81588224,\"$clusterTime\":{\"clusterTime\":{\"$timestamp\":{\"t\":1671342063,\"i\":1}},\"signature\":{\"keyId\":7151448915269648390,\"hash\":{\"$binary\":{\"base64\":\"uSUyLlJpD0NMq5fCMjcH5l1uKAk=\",\"subType\":\"00\"}}}},\"indexes\":136,\"collections\":40,\"storageSize\":68009984,\"fsUsedSize\":15365464064,\"avgObjSize\":2364.101942005046,\"ok\":1,\"db\":\"test\",\"views\":2,\"fsTotalSize\":48449372160}"
            }
        },
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 343595282432,
                "free": 98476376064,
                "threshold": 10485760,
                "exists": true
            }
        },
        "mongo": {
            "status": "UP",
            "components": {
                "getReactiveMongoTemplate": {
                    "status": "UP",
                    "details": {
                        "version": "4.4.11"
                    }
                },
                "reactiveMongoTemplate": {
                    "status": "UP",
                    "details": {
                        "version": "4.4.11"
                    }
                }
            }
        },
        "ping": {
            "status": "UP"
        }
    }
}
View Code

 

2.  Actuator详述

访问http://localhost:8099/actuator,查看暴露出来的端点:

注意如果在上例ActuatorWebSecurityConfiguration.java中设置为requestMatchers(EndpointRequest.toAnyEndpoint())则会暴露actuator下所有endpoint,如果设置为requestMatchers(EndpointRequest.to(HealthEndpoint.class, InfoEndpoint.class))则只会暴露health和info这两个端点。比如health提供应用健康情况基础信息;metrics提供一些有用应用程序指标(jvm内存使用、cpu使用等),比如访问 http://localhost:8081/actuator/metrics/jvm.memory.max得到

{"name":"jvm.memory.max","description":"The maximum amount of memory in bytes that can be used for memory management","baseUnit":"bytes","measurements":[{"statistic":"VALUE","value":6.671564799E9}],"availableTags":[{"tag":"area","values":["heap","nonheap"]},{"tag":"id","values":["Compressed Class Space","PS Old Gen","PS Survivor Space","Metaspace","PS Eden Space","Code Cache"]}]}

 

另外每个端点都可以通过配置来单独启停

{
    "_links": {
        "self": {
            "href": "http://localhost:8081/actuator",
            "templated": false
        },
        "beans": {
            "href": "http://localhost:8081/actuator/beans",
            "templated": false
        },
        "caches-cache": {
            "href": "http://localhost:8081/actuator/caches/{cache}",
            "templated": true
        },
        "caches": {
            "href": "http://localhost:8081/actuator/caches",
            "templated": false
        },
        "health": {
            "href": "http://localhost:8081/actuator/health",
            "templated": false
        },
        "health-path": {
            "href": "http://localhost:8081/actuator/health/{*path}",
            "templated": true
        },
        "info": {
            "href": "http://localhost:8081/actuator/info",
            "templated": false
        },
        "conditions": {
            "href": "http://localhost:8081/actuator/conditions",
            "templated": false
        },
        "configprops": {
            "href": "http://localhost:8081/actuator/configprops",
            "templated": false
        },
        "configprops-prefix": {
            "href": "http://localhost:8081/actuator/configprops/{prefix}",
            "templated": true
        },
        "env": {
            "href": "http://localhost:8081/actuator/env",
            "templated": false
        },
        "env-toMatch": {
            "href": "http://localhost:8081/actuator/env/{toMatch}",
            "templated": true
        },
        "loggers": {
            "href": "http://localhost:8081/actuator/loggers",
            "templated": false
        },
        "loggers-name": {
            "href": "http://localhost:8081/actuator/loggers/{name}",
            "templated": true
        },
        "heapdump": {
            "href": "http://localhost:8081/actuator/heapdump",
            "templated": false
        },
        "threaddump": {
            "href": "http://localhost:8081/actuator/threaddump",
            "templated": false
        },
        "metrics-requiredMetricName": {
            "href": "http://localhost:8081/actuator/metrics/{requiredMetricName}",
            "templated": true
        },
        "metrics": {
            "href": "http://localhost:8081/actuator/metrics",
            "templated": false
        },
        "scheduledtasks": {
            "href": "http://localhost:8081/actuator/scheduledtasks",
            "templated": false
        },
        "mappings": {
            "href": "http://localhost:8081/actuator/mappings",
            "templated": false
        }
    }
}
View Code

 

HTTP方法Endpoint描述
GET /actuator 查看有哪些 Actuator endpoint 是開放的
GET /actuator/auditevent 查看 audit 的事件,例如認證進入、訂單失敗,需要搭配 Spring security 使用,sample code
GET /actuator/beans 查看運行當下裡面全部的 bean,以及他們的關係
GET /actuator/conditions 查看自動配置的結果,記錄哪些自動配置條件通過了,哪些沒通過
GET /actuator/configprops 查看注入帶有 @ConfigurationProperties 類的 properties 值為何(包含默認值)
GET /actuator/env (常用) 查看全部環境屬性,可以看到 SpringBoot 載入了哪些 properties,以及這些 properties 的值(但是會自動*掉帶有 key、password、secret 等關鍵字的 properties 的值,保護安全資訊)
GET /actuator/flyway 查看 flyway DB 的 migration 資訊
GET /actuator/health (常用) 查看當前 SpringBoot 運行的健康指標,值由 HealthIndicator 的實現類提供(所以可以自定義一些健康指標資訊,加到這裡面)
GET /actuator/heapdump 取得 JVM 當下的 heap dump,會下載一個檔案
GET /actuator/info 查看 properties 中 info 開頭的屬性的值,沒啥用
GET /actuator/mappings 查看全部的 endpoint(包含 Actuator 的),以及他們和 Controller 的關係
GET /actuator/metrics(常用) 查看有哪些指標可以看(ex: jvm.memory.max、system.cpu.usage),要再使用/actuator/metrics/{metric.name}分別查看各指標的詳細資訊
GET /actuator/scheduledtasks 查看定時任務的資訊
POST /actuator/shutdown 唯一一個需要 POST 請求的 endpoint,關閉這個 SpringBoot 程式

 

放开所有endpoint

management.endpoints.web.exposure.include=* 

 只放开beans和mappings

management.endpoints.web.exposure.include=beans,mappings

 exclude可以用来关闭某些endpoints,比如下边语句关闭beans这个endpoint

management.endpoints.web.exposure.exclude=beans

2.1 health 

2.2 metrics端口含义

端点用来返回当前应用的各类重要度量指标,比如:内存信息、线程信息、垃圾回收信息、tomcat、数据库连接池等。

序号参数参数说明是否监控监控手段重要度
JVM
1 jvm.memory.max JVM 最大内存      
2 jvm.memory.committed JVM 可用内存 展示并监控堆内存和 Metaspace 重要
3 jvm.memory.used JVM 已用内存 展示并监控堆内存和 Metaspace 重要
4 jvm.buffer.memory.used JVM 缓冲区已用内存      
5 jvm.buffer.count 当前缓冲区数      
6 jvm.threads.daemon JVM 守护线程数 显示在监控页面  
7 jvm.threads.live JVM 当前活跃线程数 显示在监控页面;监控达到阈值时报警 重要
8 jvm.threads.peak JVM 峰值线程数 显示在监控页面  
9 jvm.classes.loaded 加载 classes 数      
10 jvm.classes.unloaded 未加载的 classes 数      
11 jvm.gc.memory.allocated GC 时,年轻代分配的内存空间      
12 jvm.gc.memory.promoted GC 时,老年代分配的内存空间      
13 jvm.gc.max.data.size GC 时,老年代的最大内存空间      
14 jvm.gc.live.data.size FullGC 时,老年代的内存空间      
15 jvm.gc.pause GC 耗时 显示在监控页面  
TOMCAT
16 tomcat.sessions.created tomcat 已创建 session 数      
17 tomcat.sessions.expired tomcat 已过期 session 数      
18 tomcat.sessions.active.current tomcat 活跃 session 数      
19 tomcat.sessions.active.max tomcat 最多活跃 session 数 显示在监控页面,超过阈值可报警或者进行动态扩容 重要
20 tomcat.sessions.alive.max.second tomcat 最多活跃 session 数持续时间      
21 tomcat.sessions.rejected 超过 session 最大配置后,拒绝的 session 个数 显示在监控页面,方便分析问题  
22 tomcat.global.error 错误总数 显示在监控页面,方便分析问题  
23 tomcat.global.sent 发送的字节数      
24 tomcat.global.request.max request 最长时间      
25 tomcat.global.request 全局 request 次数和时间      
26 tomcat.global.received 全局 received 次数和时间      
27 tomcat.servlet.request servlet 的请求次数和时间      
28 tomcat.servlet.error servlet 发生错误总数      
29 tomcat.servlet.request.max servlet 请求最长时间      
30 tomcat.threads.busy tomcat 繁忙线程 显示在监控页面,据此检查是否有线程夯住  
31 tomcat.threads.current tomcat 当前线程数(包括守护线程) 显示在监控页面 重要
32 tomcat.threads.config.max tomcat 配置的线程最大数 显示在监控页面 重要
33 tomcat.cache.access tomcat 读取缓存次数      
34 tomcat.cache.hit tomcat 缓存命中次数      
CPU
35 system.cpu.count CPU 数量      
36 system.load.average.1m load average 超过阈值报警 重要
37 system.cpu.usage 系统 CPU 使用率      
38 process.cpu.usage 当前进程 CPU 使用率 超过阈值报警  
39 http.server.requests http 请求调用情况 显示 10 个请求量最大,耗时最长的 URL;统计非 200 的请求量 重要
40 process.uptime 应用已运行时间 显示在监控页面  
41 process.files.max 允许最大句柄数 配合当前打开句柄数使用  
42 process.start.time 应用启动时间点 显示在监控页面  
43 process.files.open 当前打开句柄数 监控文件句柄使用率,超过阈值后报警 重要

 2.3. threaddump

方便日常定位问题时候查看线程情况。主要展示线程名、线程id、线程状态、是否等待锁资源、线程堆栈等信息

 2.4. headdump

访问http://localhost:8081/actuator/headdump会自动生成一个jvm堆文件headdump,使用visualvm打开此文件可以查看内存快照

 

2.5. shutdown

这个端口默认不开启,如果想开启需要

management.endpoint.shutdown.enabled=true

参考:

https://www.cnblogs.com/caoweixiong/p/15325382.html

标签:http,SpringBoot,tomcat,import,监控,actuator,Actuator,localhost,8081
From: https://www.cnblogs.com/enhance/p/16990400.html

相关文章

  • SpringBoot的TestNg之编码执行+失败重跑+发送邮件
    SpringBoot的TestNg之编码执行+失败重跑+发送邮件转载:https://blog.csdn.net/qq13933506749/article/details/120831213?spm=1001.2101.3001.6661.1&utm_medium=distribut......
  • Springboot 实现热部署
    1.spring-boot-devtools(推荐)在pom.xml中添加下面依赖<!--快重启--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devto......
  • Kotlin + SpringBoot + JPA 服务端开发
    Kotlin+SpringBoot+JPA服务端开发本篇主要介绍一下kotlin+springboot的服务端开发环境搭建1.概述Kotlin是一个基于JVM的编程语言,是IDEA开发工具jetbrai......
  • java和springboot开发祭祀小程序扫墓系统
    介绍绿色祭祀小程序,用户微信授权登录后可以发布纪念馆(祭祀名人,祭祀英烈,祭祀个人,可以设置成公开状态或者隐私状态)购买祭祀礼物和留言,用户还可以发布代祭的信息演示视频小......
  • K8S的Kafka监控(Prometheus+Grafana)
    欢迎访问我的GitHub这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos对于部署在K8S上的Kafka来说,Prometheus+Grafana是常用的监控......
  • springboot + rabbitmq发送邮件(保证消息100%投递成功并被消费)
    一、先扔一张图image.png说明:本文涵盖了关于RabbitMQ很多方面的知识点,如:消息发送确认机制消费确认机制消息的重新投递消费幂等性,等等这些都是围绕上面那张整体流程图......
  • 在springboot项目里配置ReactiveRedisTemplate
    配置pom.xml: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> ......
  • 在springboot项目集成r2dbc,集成mysql的流式代码DAO层
    我引用的是springboot2.7.0版本。在pom.xml里引入r2dbc的包,和mysql的驱动包:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot......
  • springboot配置自定义objectMapper
      packagecom.my.config;importcom.fasterxml.jackson.annotation.JsonInclude;importcom.fasterxml.jackson.core.JsonGenerator;importcom.fasterxml.jackso......
  • 【SpringBoot】使用WebSocket做消息对话
    Http协议只能客户端发送---服务器回复,无法做到服务器主动向客户端发送消息,所以可以使用websocket来进行双向通道发消息 研究了一下抖音斗鱼的弹幕也是用的websocket,......