《Spring Boot in Action》【7. Actuator】

7. Actuator

启用Actuator,你只要在build.gradle中加入:

compile 'org.springframework.boot:spring-boot-starter-actuator'

Spring Boot Actuator提供了一系列RESTful接口:

HTTP方法路径描述
GET/beansSpring应用上下文中所有bean以及它们之间的依赖关系
GET/autoconfig自动配置报告,哪些自动配置生效或无效
GET/env各种环境属性
GET/env/{name}根据名字检索环境属性
GET/configprops各种配置属性
GET/mappingsURI路径到控制器的映射
GET/metrics各种指标
GET/metrics/{name}根据名字检索指标
GET/trace最近100条HTTP请求追踪(数据在内存里)
GET/dump线程活动的快照
GET/health应用健康指标,由HealthIndicator接口的实现提供
POST/shutdown关闭应用
GET/info提供关于应用的自定义信息

这些信息主要分为三类:配置(configuration)、指标(metrics)、其他(miscellaneous)。为了安全,任何名字或者名字最后部分是“password”、“secret”或者“key”的属性,都会被打星显示。

7.1 配置信息

包括/beans、/autoconfig、/env、/env/{name}、/configprops、/mappings

7.2 指标信息

/metrics接口返回各种指标,按照前缀分类:

分类前缀描述
垃圾收集器gc.*mark-sweep和scavenge垃圾收集器的垃圾收集计数和持续时间 (from java.lang.management.GarbageCollectorMXBean)
内存mem.*分配给应用的内存和空闲的内存 (from java.lang.Runtime)
heap.*当前内存使用 (from java.lang .management.MemoryUsage)
类加载器classes.*JVM类加载器加载和未加载的类数量 (from java.lang.management.ClassLoadingMXBean)
系统processors,uptime,instance.uptime,systemload.average处理器数量 (from java.lang.Runtime),运行时间 (from java.lang.management.RuntimeMXBean),平均系统负载 (from java.lang.management.OperatingSystemMXBean)
线程池threads.*线程、守护线程的数量,以及JVM启动以来的线程峰值 (from java.lang.management.ThreadMXBean)
数据源datasource.*数据源连接数量 (from the data source’s metadata,仅当存在datasource bean时才有)
HTTP会话httpsessions.*活跃的和最大的会话数量 (from the embedded Tomcat bean,仅当有内置服务器时才有)
HTTPcounter.status.,gauge.response.HTTP请求的各种度量和统计

/health接口返回各种健康指标:

Health indicatorKeyReports
ApplicationHealthIndicatornoneAlways “UP”
DataSourceHealthIndicatordb“UP” and database type if the database can be contacted; “DOWN” status otherwise
DiskSpaceHealthIndicatordiskSpace“UP” and available disk space, and “UP” if available space is above a threshold; “DOWN” if there isn’t enough disk space
JmsHealthIndicatorjms“UP” and JMS provider name if the message broker can be contacted; “DOWN” otherwise
MailHealthIndicatormail“UP” and the mail server host and port if the mail server can be contacted; “DOWN” otherwise
MongoHealthIndicatormongo“UP” and the MongoDB server version; “DOWN” otherwise
RabbitHealthIndicatorrabbit“UP” and the RabbitMQ broker version; “DOWN” otherwise
RedisHealthIndicatorredis“UP” and the Redis server version; “DOWN” otherwise
SolrHealthIndicatorsolr“UP” if the Solr server can be contacted; “DOWN” otherwise

假设你需要关闭你的应用,比如在微服务架构中,你需要优雅地关闭其中一个应用实例,你可以这样:

curl -X POST http://localhost:8080/shutdown

显然,关闭应用是危险的行为,因此/shutdown默认是不启用的,你需要设置endpoints.shutdown.enabled为true才能开启,同时你应该注意/shutdown接口的权限。

/info接口返回应用的信息,默认返回空的JSON对象({}),你通过配置info打头的属性来添加更多返回:

info:
  contact:
    email: support@myreadinglist.com
    phone: 1-888-555-1971

7.3 Remote Shell

Spring Boot集成了CRaSH(可内置在Java应用中的shell),并提供了一系列命令,首先加入依赖:

compile("org.springframework.boot:spring-boot-starter-remote-shell")

然后待应用起来之后,你可以使用SSH连上去(端口2000),密码就是log里打印出来的那串随机密码:

ssh user@localhost -p 2000

可以使用由Spring Boot提供的命令:autoconfig、beans、metrics(可以看到动态更新,Ctrl-C退出),但是并不是每个Web接口都有对应的命令,这时候你需要endpoint命令:

endpoint list

这会返回endpoint列表,不过不是url,而是它们的bean name:

requestMappingEndpoint
environmentEndpoint
healthEndpoint
beansEndpoint
infoEndpoint
metricsEndpoint
traceEndpoint
dumpEndpoint
autoConfigurationReportEndpoint
configurationPropertiesReportEndpoint

然后使用endpoint invoke命令(去掉“Endpoint”后缀):

endpoint invoke health

7.4 自定义

7.4.1 修改endpoint IDs

每个Actuator endpoint都有一个ID来决定路径,比如/beans的默认ID就是beans,通过修改endpoints.endpoint-id.id属性就能修改路径,比如修改/shutdown为/kill:

endpoints:
  shutdown:
    id: kill

7.4.2 禁用(启用)endpoints

你还可以禁用某些endpoint:

endpoints:
  metrics:
    enabled: false

你可以禁用所有,并启用某些:

endpoints:
  enabled: false
  metrics:
    enabled: true

7.4.3 添加自定义metrics和gauges

比如我们需要记录用户保存了几次书到reading list,以及最后一次保存的时间,并通过/metrics暴露出来,Actuator为我们自动配置了一个CounterService实例,帮助完成计数功能:

package org.springframework.boot.actuate.metrics;

public interface CounterService {
  void increment(String metricName);
  void decrement(String metricName);
  void reset(String metricName);
}

还有一个GaugeService实例,帮助给一个指标设置一个值:

package org.springframework.boot.actuate.metrics;

public interface GaugeService {
  void submit(String metricName, double value);
}

你只需要注入这两个bean,然后直接调用方法即可:

@RequestMapping(method = RequestMethod.POST)
public String addToReadingList(Reader reader, Book book) {

  book.setReader(reader);
  readingListRepository.save(book);

  counterService.increment("books.saved");
  gaugeService.submit("books.last.saved", System.currentTimeMillis());

  return "redirect:/";
}

对于稍微复杂点的metrics,上面那两个Service估计不够用了,这时候你可以实现PublicMetrics接口:

package org.springframework.boot.actuate.endpoint;

public interface PublicMetrics {
  Collection<Metric<?>> metrics();
}

比如,我们要知道application context启动的时间,bean的数量,bean定义的数量以及注解为@Controller的bean的数量:

package readinglist;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

@Component
public class ApplicationContextMetrics implements PublicMetrics {

  @Autowired
  private ApplicationContext context;

  @Override
  public Collection<Metric<?>> metrics() {
    List<Metric<?>> metrics = new ArrayList<Metric<?>>();
    metrics.add(new Metric<Long>("spring.context.startup-date", context.getStartupDate()));
    metrics.add(new Metric<Integer>("spring.beans.definitions", context.getBeanDefinitionCount()));
    metrics.add(new Metric<Integer>("spring.beans", context.getBeanNamesForType(Object.class).length));
    metrics.add(new Metric<Integer>("spring.controllers", context.getBeanNamesForAnnotation(Controller.class).length));
    return metrics;
  }
}

然后访问/metrics,就会显示我们自定义的指标:

{
  ...
  spring.context.startup-date: 1429398980443,
  spring.beans.definitions: 261,
  spring.beans: 272,
  spring.controllers: 2,
  books.count: 1,
  gauge.books.save.time: 1429399793260,
  ...
}

spring.controllers为2,是因为统计了ReadingListController和Spring Boot提供的BasicErrorController。

7.4.4 添加自定义trace repository

/trace接口默认使用容量为100的内存repository,我们可以自己声明InMemoryTraceRepository bean,比如设置容量为1000:

package readinglist;

import org.springframework.boot.actuate.trace.InMemoryTraceRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ActuatorConfig {

  @Bean
  public InMemoryTraceRepository traceRepository() {
    InMemoryTraceRepository traceRepo = new InMemoryTraceRepository();
    traceRepo.setCapacity(1000);
    return traceRepo;
  }

}

虽然容量是增加了,但还是消耗内存,而且没有持久化,所以我们可以自己实现Spring Boot的TraceRepository接口:

package org.springframework.boot.actuate.trace;

import java.util.List;
import java.util.Map;

public interface TraceRepository {
  List<Trace> findAll();
  void add(Map<String, Object> traceInfo);
}

比如实现存到MongoDB:

package readinglist;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.trace.Trace;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.stereotype.Service;

@Service
public class MongoTraceRepository implements TraceRepository {

  @Autowired
  private MongoOperations mongoOps;

  @Override
  public List<Trace> findAll() {
    return mongoOps.findAll(Trace.class);
  }

  @Override
  public void add(Map<String, Object> traceInfo) {
    mongoOps.save(new Trace(new Date(), traceInfo));
  }
}

你只要加入MongoDB的starter,就会自动配置好MongoOperations bean:

compile("org.springframework.boot:spring-boot-starter-data-mongodb")

7.4.5 自定义健康指标

比如我们要添加一个检测Amazon能否访问的健康指标:

package readinglist;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class AmazonHealth implements HealthIndicator {

  @Override
  public Health health() {
    try {
      RestTemplate rest = new RestTemplate();
      rest.getForObject("http://www.amazon.com", String.class);
      return Health.up().build();
    } catch (Exception e) {
      return Health.down().build();
    }
  }
}

如果需要更详细的信息,可以调用withDetail()方法,比如把catch中的代码改成:

return Health.down().withDetail("reason", e.getMessage()).build();

7.5 Actuator接口安全

给Actuator路径加权限和一般的路径加权限是一样的,但是要用antMatchers把所有接口列一遍显然比较麻烦,所以可以配置一个公共的前缀:

management:
  context-path: /mgmt

然后就在SecurityConfig.java中的configure()方法中加入:

.antMatchers("/mgmt/**").access("hasRole('ADMIN')")
Summary A developer-focused guide to writing applications using Spring Boot. You'll learn how to bypass the tedious configuration steps so that you can concentrate on your application's behavior. Purchase of the print book includes a free eBook in PDF, Kindle, and ePub formats from Manning Publications. About the Technology The Spring Framework simplifies enterprise Java development, but it does require lots of tedious configuration work. Spring Boot radically streamlines spinning up a Spring application. You get automatic configuration and a model with established conventions for build-time and runtime dependencies. You also get a handy command-line interface you can use to write scripts in Groovy. Developers who use Spring Boot often say that they can't imagine going back to hand configuring their applications. About the Book Spring Boot in Action is a developer-focused guide to writing applications using Spring Boot. In it, you'll learn how to bypass configuration steps so you can focus on your application's behavior. Spring expert Craig Walls uses interesting and practical examples to teach you both how to use the default settings effectively and how to override and customize Spring Boot for your unique environment. Along the way, you'll pick up insights from Craig's years of Spring development experience. What's Inside Develop Spring apps more efficiently Minimal to no configuration Runtime metrics with the Actuator Covers Spring Boot 1.3 About the Reader Written for readers familiar with the Spring Framework. About the Author Craig Walls is a software developer, author of the popular book Spring in Action, Fourth Edition, and a frequent speaker at conferences.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值