面试官:聊一聊SpringBoot服务监控机制

前言

任何一个服务若是没有监控,那就是两眼一抹黑,没法知道当前服务的运行状况,也就没法对可能出现的异常情况进行很好的处理,因此对任意一个服务来讲,监控都是必不可少的。java

就目前而言,大部分微服务应用都是基于 SpringBoot 来构建,因此了解 SpringBoot 的监控特性是很是有必要的,而 SpringBoot 也提供了一些特性来帮助咱们监控应用。web

本文基于 SpringBoot 2.3.1.RELEASE 版本演示。spring

SpringBoot 监控

SpringBoot 中的监控能够分为 HTTP 端点和 JMX 两种方式来监控当前应用的运行情况和指标收集json

HTTP Endpoints 监控

执行器端点容许您监视应用程序并与之交互。SpringBoot 包括许多内置的端点,并容许咱们添加本身的端点。能够经过 HTTPJMX 启用或禁用每一个端点,并公开(使其能够远程访问)。每一个端点都有一个惟一的 id,访问时能够经过以下地址进行访问:http:ip:port/{id}(SpringBoot 1.x ),而在 SpringBoot 2.x 版本中,默认新增了一个 /actuator 做为基本路,访问地址则对应为 :http:ip:port/actuator/{id}缓存

使用 HTTP 监控很是简单,在 SpringBoot 项目中,引入以下依赖:tomcat

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

默认就能够经过地址 http:localhost:8080/actuator/health,访问以后获得以下结果:安全

image

SpringBoot 中提供了很是多的默认端点监控,可是出于安全考虑,默认状况下有些端点并非开启状态,如 shutdown 端点就是默认关闭的。springboot

内置端点

SpringBoot 中默认提供的经常使用内置端点以下:服务器

端点 id 描述
auditevents 公开当前应用程序的审计事件信息,须要 AuditEventRepository Bean。
beans 展现程序中全部的 Bean。
caches 公开可用的缓存。
conditions 展现配置类或者自动装配类中的条件,以及它们匹配或者不匹配的缘由。
configprops 显示全部 @ConfigurationProperties 中的配置属性。
env 显示 ConfigurableEnvironment 中的全部环境。
health 显示应用程序运行情况信息。
httptrace 显示 HTTP 跟踪信息(默认状况下统计最近 100 次请求),须要 HttpTraceRepository Bean。
info 显示任意程序信息。
integrationgraph 显示 Spring 集成图,须要依赖 spring-integration-core。
loggers 展现和修改应用中的 loggers 配置。
metrics 展现当前应用监控指标的度量。
mappings 展现全部 @RequestMapping 路径。
scheduledtasks 展现应用中的全部定时任务信息。
sessions 容许从 Spring 会话支持的会话存储中检索和删除用户会话。须要使用基于 Spring Session web应用程序。
shutdown 优雅的关闭程序,默认禁止了该端点的访问。

虽说这里的大部分端点都是默认开启的,可是默认暴露(容许对外访问)的只有 healthinfo 端点,因此若是须要容许端点对外暴露,能够经过以下配置(若是想要暴露全部的端点,则能够直接配置 "*" ):session

management:
  endpoints:
    web:
      exposure:
        include: [health,info,mappings] //或者直接配置 "*"

另外,开启或禁用某一个端点,也能够经过经过以下配置进行动态控制:

management.endpoint.<id>.enabled=true

接下来咱们挑选几个重点的端点来介绍一下。

health 端点

health 断点默认只是展现当前应用健康信息,可是咱们能够经过另外一个配置打开详细信息,这样不只仅会监控当前应用,还会监控与当前应用相关的其余第三方应用,如 Redis

management:
  endpoint:
    health:
      show-details: always

这个配置打开以后,咱们链接上 Redis 以后再次访问 health 端点,就能够展现 Redis 服务的健康信息了:

image

loggers 端点

访问 http://localhost:8080/actuator/loggers 能够查看当前应用的日志级别等信息:

image

这里面自己并不特别,可是有一个功能却很是有用,好比咱们生产环境日志级别通常都是 info,可是如今有一个 bug 经过 info 级别没法排查,那么咱们就能够临时修改 log 级别。

好比上图中的 ROOT 节点是 info 级别,那么咱们能够经过 postman 等工具来发一个 post 请求修改日志级别。

image

修改以后就会发现,日志由原来的 info 变成了 debug

image

metrics 端点

metrics 是一个很是重要的监控端点,其监控内容覆盖了 JVM 内存、堆、类加载、处理器和 tomcat 容器等一些重要指标:

image

能够看到这里面包含了很是多的指标,任意访问一个指标就能够查看对应的指标信息:

image

自定义监控端点

经过上面的介绍,能够看到 SpringBoot 提供的监控很是强大,可是就算再全面的监控也不可能知足全部人的需求,因此 SpringBoot 也支持自定义监控端点。

自定义监控端点经常使用注解

自定义一个监控端点主要有以下经常使用注解:

  • @Endpoint:定义一个监控端点,同时支持 HTTPJMX 两种方式。
  • @WebEndpoint:定义一个监控端点,只支持 HTTP 方式。
  • @JmxEndpoint:定义一个监控端点,只支持 JMX 方式。

以上三个注解做用在类上,表示当前类是一个监控端点,另外还有一些注解会用在方法和参数上:

  • @ReadOperation:做用在方法上,可用来返回端点展现的信息(经过 Get 方法请求)。
  • @WriteOperation:做用在方法上,可用来修改端点展现的信息(经过 Post 方法请求)。
  • @DeleteOperation:做用在方法上,可用来删除对应端点信息(经过 Delete 方法请求)。
  • @Selector:做用在参数上,用来定位一个端点的具体指标路由。

来,一块儿写一个本身的监控端点

  • 定义一个类,并使用 @Endpoint 注解标注标识,同时定义几个方法用 @ReadOperation@WriteOperation 注解来标注:
@Endpoint(id="myEndpoint")
@Component
public class MyEndpoint {
    private String STATUS = "up";
    private String DETAIL = "一切正常";

//    @ReadOperation
//    public String test1(){
//        return "wolf";
//    }

//    @ReadOperation
//    public Map<String,String> test2(){
//        Map<String,String> map = new HashMap();
//        map.put("status","up");
//        return map;
//    }

    @ReadOperation
    public JSONObject test3(){
        JSONObject jsonObject= new JSONObject();
        jsonObject.put("status",STATUS);
        jsonObject.put("detail",DETAIL);
        return jsonObject;
    }

    @ReadOperation
    public JSONObject test3_1(@Selector String name){
        JSONObject jsonObject= new JSONObject();
        if ("status".equals(name)){
            jsonObject.put("status",STATUS);
        }else if ("detail".equals(name)){
            jsonObject.put("detail",DETAIL);
        }
        return jsonObject;
    }

    @WriteOperation//动态修改指标
    public void test4(@Selector String name,@Nullable String value){
        if (!StringUtils.isEmpty(value)){
            if ("status".equals(name)){
                STATUS = value;
            }else if ("detail".equals(name)){
                DETAIL = value;
            }
        }
    }
}
  1. @Component 注解表示将该类交给 Spring 进行管理,或者也能够再定义一个 Configuration 类来加载该 Bean 也能够,固然,若是咱们须要提供给第三方使用,若是没法保证当前包名被扫描,则须要使用 SpringBoot 的自动装配机制将该类进行管理。
  2. @ReadOperation 方法能够返回 String 或者 JSONObject 或者 Map 集合等。
  3. 参数上加了 @Selector 注解则表示访问断端点的时候能够直接访问子节点。

完成了上面的类,启动 SpringBoot 应用,接下来就能够直接经过 http://localhost:8080/actuator/myEndpoint 进行访问了:

image

同时,由于 test3_1 方法使用了 @Selector 注解,因此咱们能够经过这个方法每个指标的明细:

image

而带有 @WriteOperation 注解的方法能够用来修改指标,这个方法须要用 post 进行访问,访问的参数能够直接使用字符串传参,也能够直接使用 json 进行传参,修改以后再次查看就能够发现指标已经被动态修改:

image

JMX 监控

JMX 全称为 Java Management Extensions,即 Java 管理扩展。它提供了对 Java 应用程序和 JVM 的监控管理。经过JMX 咱们能够监控服务器中各类资源的使用状况以及线程,内存和 CPU 等使用状况。

打开 jdk 下提供的工具 jConsole

image

打开以后这里会监控到咱们已经启动的应用,双击进入:

image

如何手动注册一个 JMX MBean

  • 定义一个接口 SystemInfoMBean(注意名字必需要用 MBean 结尾):
public interface SystemInfoMBean {
    int getCpuCore();
    long getTotalMemory();
    void shutdown();
}
  • 再定义一个类实现 SystemInfoMBean 接口,实现类的明明方式为接口名去掉 MBean
public class SystemInfo implements SystemInfoMBean {
    @Override
    public int getCpuCore() {
        return Runtime.getRuntime().availableProcessors();
    }
    @Override
    public long getTotalMemory() {
        return Runtime.getRuntime().totalMemory();
    }

    @Override
    public void shutdown() {
        System.exit(0);
    }
}
  • 最后就是须要将该实现类进行注册:
public class JmxRegisterMain {
    public static void main(String[] args) throws NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException, MalformedObjectNameException, IOException {
        MBeanServer mBeanServer= ManagementFactory.getPlatformMBeanServer();
        ObjectName objectName=new ObjectName("com.lonely.wolf.note.springboot.actuator.jmx:type=SystemInfo");
        SystemInfo SystemInfo =new SystemInfo();
        mBeanServer.registerMBean(SystemInfo,objectName);//注册
        System.in.read();//防止程序结束
    }
}

运行该 main 方法,再打开 jConsole 就能够看到成功注册了一个 MBean

image

一样的,Spring 当中只要咱们使用了 @@Endpoint 或者 @JmxEndpoint 注解,就会自动帮咱们注册一个 MBean,其原理也是利用了自动装配机制。

其余监控

除了 SpringBoot 自带的监控以外,也有其余第三方开源的强大监控系统,如 Prometheus,并且 SpringBoot 也将其进行了集成,使用 Prometheus 时只须要引入以下 jar 包便可:

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

固然,若是使用 Prometheus 的话须要单独安装,并且通常会选择 Prometheus + Grafana 来共同实现一个监控平台,在这里就不作过多介绍,若是感兴趣的朋友能够本身去了解下这两种软件的使用。

总结

本文主要讲述了 Spring Boot actuator 的使用,并分别介绍了其中两种监控类型 HTTPJMX,最后经过一个例子来实现了自定义的端点,同时也实现了手动注册一个 MBean 的方法。

相关文章
相关标签/搜索