logo头像
Snippet 博客主题

springboot中使用actuator进行监控

  • 本文springboot版本:1.5.4.RELEASE,springcloud版本:Dalston.SR5
  • 如果使用springboot2.x,请参考springboot2.x-actuator

spring-boot-actuator模块提供了一个监控和管理生产环境的模块,可以使用http、jmx、ssh、telnet等来管理和监控应用。审计(Auditing)、 健康(health)、数据采集(metrics gathering)会自动加入到应用里面。

添加依赖

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

可以在你的application.yml配置文件配置:

##运行状态 actuator监控
endpoints:
  enabled: true
  info:
    sensitive: false
  health:
    sensitive: false
management:
  ##服务路径
  context-path: /
  ##服务端口
  port: 8081

如果你使用application.properties,可以做类似的配置:

endpoints.enabled=true
endpoints.info.sensitive=false
endpoints.health.sensitive=false
management.context-path=/
management.port=8081

启动后可以看到以下日志:

2017-03-15 15:50:58.775  INFO 9544 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Detected ResponseBodyAdvice bean in org.springframework.boot.actuate.autoconfigure.EndpointWebMvcHypermediaManagementContextConfiguration$ActuatorEndpointLinksAdvice
2017-03-15 15:50:58.956  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-03-15 15:50:58.957  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-03-15 15:50:58.958  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2017-03-15 15:50:58.958  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-03-15 15:50:58.959  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/health || /health.json],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(java.security.Principal)
2017-03-15 15:50:58.960  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-03-15 15:50:58.960  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-03-15 15:50:58.961  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-03-15 15:50:58.963  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
2017-03-15 15:50:58.964  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/actuator || /actuator.json],produces=[application/json]}" onto public org.springframework.hateoas.ResourceSupport org.springframework.boot.actuate.endpoint.mvc.HalJsonMvcEndpoint.links()
2017-03-15 15:50:58.965  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/info || /info.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-03-15 15:50:58.973  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2017-03-15 15:50:58.973  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/env || /env.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-03-15 15:50:58.974  INFO 9544 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()

接口

接口 描述 敏感
actuator 列出所有可用接口 true
autoconfig 显示一个auto-configuration的报告,该报告展示所有auto-configuration候选者及它们被应用或未被应用的原因 true
beans 显示应用中所有Spring Beans的完整列表 true
configprops 显示一个所有@ConfigurationProperties的整理列表 true
dump 显示当前应用线程状态信息 true
env 显示Spring的ConfigurableEnvironment属性 true
health 展示应用的健康信息(当使用一个未认证连接访问时显示一个简单的’status’,使用认证连接访问则显示全部信息详情) false
info 显示应用信息 false
metrics 展示当前应用的’指标’信息 true
mappings 显示一个所有@RequestMapping路径的整理列表 true
shutdown 允许应用以优雅的方式关闭(默认情况下不启用) true
trace 显示trace信息(默认情况下是最后100个HTTP请求) true
loggers 显示和修改应用程序中loggers配置的功能 true

测试几个接口

/health

访问http://127.0.0.1:8081/health 可以看到

{
    "status":"UP",
    "hello":{
        "status":"UP"
    },
    "diskSpace":{
        "status":"UP",
        "total":116333809664,
        "free":86622515200,
        "threshold":10485760
    },
    "db":{
        "status":"UP",
        "database":"Oracle",
        "hello":"Hello"
    }
}  
自动配置的HealthIndicators

下面的HealthIndicators会被Spring Boot自动配置(在合适的时候):

名字 描述
CassandraHealthIndicator 检查Cassandra database是否正常
DiskSpaceHealthIndicator 低磁盘空间检测
DataSourceHealthIndicator 检查数据库连接是否正常
ElasticsearchHealthIndicator 检查Elasticsearch cluster是否正常
JmsHealthIndicator 检查JMS broker是否正常
MailHealthIndicator 检查mail server是否正常
MongoHealthIndicator 检查Mongo database是否正常
RabbitHealthIndicator 检查Rabbit server是否正常
RedisHealthIndicator 检查Redis server是否正常
SolrHealthIndicator 检查Solr server是否正常
编写自定义HealthIndicators

想提供自定义健康信息,你可以注册实现了HealthIndicator接口的Spring beans。你需要提供一个health()方法的实现,并返回一个Health响应。Health响应需要包含一个status和可选的用于展示的详情。比如上面/health接口中的hello就是再下面定义的

@Component
public class HelloHealthIndicator implements HealthIndicator {
    @Override
    public Health health() {
        int errorCode = check(); // perform some specific health check
        if (errorCode != 0) {
            return Health.down().withDetail("Error Code", errorCode)  .build();
        }
        return Health.up().build();
    }

    int check(){
        return 0;
    }
}

/metrics

{
    "counter.status.200.root": 20,
    "counter.status.200.metrics": 3,
    "counter.status.200.star-star": 5,
    "counter.status.401.root": 4,
    "gauge.response.star-star": 6,
    "gauge.response.root": 2,
    "gauge.response.metrics": 3,
    "classes": 5808,
    "classes.loaded": 5808,
    "classes.unloaded": 0,
    "heap": 3728384,
    "heap.committed": 986624,
    "heap.init": 262144,
    "heap.used": 52765,
    "nonheap": 0,
    "nonheap.committed": 77568,
    "nonheap.init": 2496,
    "nonheap.used": 75826,
    "mem": 986624,
    "mem.free": 933858,
    "processors": 8,
    "threads": 15,
    "threads.daemon": 11,
    "threads.peak": 15,
    "threads.totalStarted": 42,
    "uptime": 494836,
    "instance.uptime": 489782,
    "datasource.primary.active": 5,
    "datasource.primary.usage": 0.25
}  

此处我们可以看到基本的 memory , heap , class loading , processor 和 thread pool 信息,连同一些HTTP指标,还可以使用 / /{name:.*} 访问单个属性。在该实例中, root (‘/‘), /metrics URLs分别返回20次,3次 HTTP 200 响应。同时可以看到 root URL返回了4次 HTTP 401 (unauthorized)响应。双asterix(star-star)来自于被Spring MVC /** 匹配到的一个请求(通常为一个静态资源)。
gauge 级别展示了一个请求的最后响应时间。所以, root 的最后请求被响应耗时2毫秒, /metrics 耗时3毫秒。

Spring Boot提供以下系统指标:
系统内存总量(mem),单位:Kb
空闲内存数量(mem.free),单位:Kb
处理器数量(processors)
系统正常运行时间(uptime),单位:毫秒
应用上下文(就是一个应用实例)正常运行时间(instance.uptime),单位:毫秒
系统平均负载(systemload.average)
堆信息(heap,heap.committed,heap.init,heap.used),单位:Kb
线程信息(threads,thread.peak,thead.daemon)
类加载信息(classes,classes.loaded,classes.unloaded)
垃圾收集信息(gc.xxx.count, gc.xxx.time)

还会为你应用中定义的支持的DataSource提供 以下指标:
最大连接数(datasource.xxx.max)
最小连接数(datasource.xxx.min)
活动连接数(datasource.xxx.active)
连接池的使用情况( .xxx.usage)

所有的数据源指标共用 datasoure. 前缀。该前缀对每个数据源都非常合适:
如果是主数据源(唯一可用的数据源或存在的数据源中被@Primary标记的)前缀为datasource.primary
如果数据源bean名称以dataSource结尾,那前缀就是bean的名称去掉dataSource的部分(例如,batchDataSource的前
缀是datasource.batch)
其他情况使用bean的名称作为前缀

记录自己的指标

想要记录你自己的指标,只需将CounterServiceGaugeService注入到你的bean中。CounterService提供increment:将指定的计数器增加1。,decrement:将指定的计数器减1。和reset:复位指定的计数器。 方法;GaugeService提供一个submit方法。

@Service
public class UserService {
    @Autowired
    UserMapper mapper;

    @Autowired
    CounterService counterService;

    @Autowired
    GaugeService gaugeService;

    public Map<Object, Object> findById(String id) {
        this.counterService.increment("services.system.userService.findById.invoked");
        gaugeService.submit("a", 1.0);
        return mapper.findById(id);
    }
}

/trace

访问http://127.0.0.1:8081/trace

[
    {
        "timestamp":1489568887768,
        "info":{
            "method":"GET",
            "path":"/",
            "headers":{
                "request":{
                    "host":"127.0.0.1:8080",
                    "connection":"keep-alive",
                    "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                    "upgrade-insecure-requests":"1",
                    "user-agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0",
                    "accept-encoding":"gzip, deflate, sdch",
                    "accept-language":"zh-CN,zh;q=0.8"
                },
                "response":{
                    "X-Application-Context":"youyu:localdev:8080",
                    "status":"404"
                }
            }
        }
    },
    {
        "timestamp":1489568886967,
        "info":{
            "method":"GET",
            "path":"/",
            "headers":{
                "request":{
                    "host":"127.0.0.1:8080",
                    "connection":"keep-alive",
                    "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                    "upgrade-insecure-requests":"1",
                    "user-agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0",
                    "accept-encoding":"gzip, deflate, sdch",
                    "accept-language":"zh-CN,zh;q=0.8"
                },
                "response":{
                    "X-Application-Context":"youyu:localdev:8080",
                    "status":"404"
                }
            }
        }
    }
]

/loggers

访问http://127.0.0.1:8081/loggers返回:

{
    "levels":[
        "OFF",
        "ERROR",
        "WARN",
        "INFO",
        "DEBUG",
        "TRACE"
    ],
    "loggers":{
        "ROOT":{
            "configuredLevel":"INFO",
            "effectiveLevel":"INFO"
        },
        "com":{
            "configuredLevel":null,
            "effectiveLevel":"INFO"
        },
        "com.caiyi":{
            "configuredLevel":null,
            "effectiveLevel":"INFO"
        }
        ...
    }
}

可以通过post请求http://127.0.0.1:8081/loggers/{elephant}修改不同包下的日志级别。
举个栗子:访问

http:127.0.0.1:8081/manage/loggers/com.caiyi

请求body中传参数:

{
    "configuredLevel": "debug"
}

就能修改com.caiyi下面的日志级别为debug,用get请求一下http://127.0.0.1:8081/manage/loggers/com.caiyi
可看到修改成功了:

{
    "configuredLevel": "DEBUG",
    "effectiveLevel": "DEBUG"
}
微信打赏

赞赏是不耍流氓的鼓励