2019-01-02 · Develop

监控 Spring Boot 应用

在 Spring Boot 的众多模块中,有一个特殊的模块 Actuator ,其主要用来暴露应用本身信息,所以它就是作用于对用于的监控和管理。对于中小团队来说,可以有效的减少监控系统在采集应用指标的开发量。当然,默认提供的功能并不能满足所有用户的需求,因此 Spring Boot 团队也提供了进行自定义监控的实现方式。

初识 Actuator

Spring Boot 应用集成 Actuator 是非常容易的,只需在 pom 文件中添加如下的代码

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

然后启动应用,访问 http://localhost:8080/actuator 将会看到如下的信息

{
    "_links": {
        "self": {
            "href": "http://localhost:8080/actuator",
            "templated": false
        },
        "health": {
            "href": "http://localhost:8080/actuator/health",
            "templated": false
        },
        "health-component": {
            "href": "http://localhost:8080/actuator/health/{component}",
            "templated": true
        },
        "health-component-instance": {
            "href": "http://localhost:8080/actuator/health/{component}/{instance}",
            "templated": true
        },
        "info": {
            "href": "http://localhost:8080/actuator/info",
            "templated": false
        }
    }
}

访问其中的其中的健康信息端点 http://localhost:8080/actuator/health 就可以获取到应用的健康信息

{
    "status": "UP"
}

默认情况下我们只能获取到关于 health 和 info 的信息,如果需要获取更多的监控信息,需要配置暴露 Set 集合,如下配置暴露所有的监控信息

management:
  endpoints:
    web:
      exposure:
        include: "*"

主要暴露的功能

Spring Boot 应用提供了很多的监控信息,下面罗列部分比较常用的功能。

HTTP 跟踪

通过浏览器输入 http://localhost:8080/actuator/httptrace 就可以访问 Spring Boot 提供的 trace 跟踪功能。 trace 通过 InMemoryHttpTraceRepository 类来实现的,默认保留最后 100 条访问数据,当然也可以指定些个性化的设置。比如设置保留最后一条记录。

    @Bean
    @ConditionalOnMissingBean(InMemoryHttpTraceRepository.class)
    public InMemoryHttpTraceRepository inMemoryHttpTraceRepository() {
        InMemoryHttpTraceRepository inMemoryHttpTraceRepository = new InMemoryHttpTraceRepository();
        inMemoryHttpTraceRepository.setCapacity(1);
        return inMemoryHttpTraceRepository;
    }

日志查看

Actuator 允许查看日志配置,还允许修改日志等级配置,也可以在线查看日志内容。只需在浏览器中输入如下的地址:

http://localhost:8080/actuator/loggers

堆栈信息

在 Spring Boot 中,可以获取某一时刻虚拟机的线程栈信息,改信息类似使用 JDK 自带的 jstack 命令的输出结果。http://localhost:8080/actuator/threaddump

JDK 提供的 jmap 工具,能够获取内存镜像信息,同样 Actuator 能够将镜像信息下载下来以提供分析 http://localhost:8080/actuator/heapdump 。 将下载下来的 heapdump 文件使用 jhat -port 7000 heapdump 这个命令进行打开,然后访问 http://localhost:7000/oql/ 可以对其进行 OQL 查询来分析内存信息。比如查询 ArrayList 的 size 超出 400 的实例

select s from java.util.ArrayList s where s.size > 400

查看 URL 映射

Actuator 的 mappings 输出所以通过注解 @RequestMapping 设置的 URL 映射,访问如下地址 http://localhost:8080/actuator/mappings 将返回如下相似信息。

{
    "handler": "public com.baomidou.mybatisplus.extension.api.R<com.baomidou.mybatisplus.core.metadata.IPage<com.zuojl.lo.modules.sys.entity.User>> com.zuojl.lo.modules.sys.controller.UserController.page(int,int)",
    "predicate": "{GET /user/list}",
    "details": {
        "handlerMethod": {
            "className": "com.zuojl.lo.modules.sys.controller.UserController",
            "name": "page",
            "descriptor": "(II)Lcom/baomidou/mybatisplus/extension/api/R;"
        },
        "requestMappingConditions": {
            "consumes": [],
            "headers": [],
            "methods": [
                "GET"
            ],
            "params": [],
            "patterns": [
                "/user/list"
            ],
            "produces": []
        }
    }
}

查看 Spring 容器所管理的 Bean

Actuator 的 beans 输出所以 Spring 管理的 Bean ,输出如下

{
    "userController": {
        "aliases": [],
        "scope": "singleton",
        "type": "com.zuojl.lo.modules.sys.controller.UserController",
        "resource": "file [D:\\IdeaProjects\\lo\\target\\classes\\com\\zuojl\\lo\\modules\\sys\\controller%userController.class]",
        "dependencies": [
            "userServiceImpl"
        ]
    }
}

其他监控

编写自己的监控信息

下面简单编写一个输出当前系统时间,并按照指定格式进行格式化。

创建监控实现类

@Endpoint(id = "date")
public class DateEndpoint {

    private String format = "yyyy-MM-dd HH:mm:ss";

    @ReadOperation
    public Map<String, Object> info() {
        Map<String, Object> map = new HashMap<>();
        Date date = new Date();
        map.put("time", date.getTime());
        map.put("format", format);
        map.put("date", new SimpleDateFormat(format).format(date));
        return map;
    }

    @WriteOperation
    public void setFormat(String format) {
        this.format = format;
    }
}

三个注解 @Endpoint 表示这是一个自定义的监控类,可以通过 id 属性来设置 url 的路径,方法上使用 @ReadOperation@WriteOperation 两个注解来分别表示显示监控指标和动态更改监控指标。

然后将其注册为 Spring 的 Bean

@Configuration
public class DateEndpointConfig {
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnEnabledEndpoint
    public DateEndpoint dateEndpoint() {
        return new DateEndpoint();
    }
}

然后配置暴露监控

management:
  endpoints:
    web:
      exposure:
        include: "date"

现在访问 http://localhost:8080/actuator/date 路径将返回如下的信息

{
    "date": "2019-01-04 15:27:23",
    "format": "yyyy-MM-dd HH:mm:ss",
    "time": 1546586843852
}

然后修改 format 的格式

curl -XPOST 'http://127.0.0.1:8080/actuator/date' -H 'Content-Type:application/json' -d '{"format":"yyyy-MM-dd"}'

现在访问将返回如下的信息

{
    "date": "2019-01-04",
    "format": "yyyy-MM-dd",
    "time": 1546587525789
}