微服务与监控
微服务应用采用分布式部署方式,大部分应用都是运行在不同的机器上,彼此通过http等方式进行交互,前后台的业务流会经过很多个微服务的处理和传递,出现异常如何快速定位是哪个环节出现问题,这是微服务架构不得不面对和解决的一个问题。这就是应用监控。
微服务应用监控是一个很大的话题,本文试图加以总结。
监控什么-what
服务概要信息、服务健康指标、服务请求映射、服务调用链、服务API监控、服务内部组件状态、服务性能指标;
- 对于一个微服务,需要监控的信息很多,每个微服务是一个微型独立的服务,麻雀虽小,五脏俱全,从UI到DB;
- 而一个复杂的系统可能涉及到上百个服务节点部署,所以掌控一个微服务的健康指标、环境配置、服务配置、请求映射、spring bean、请求trace信息、日志信息,Rest API服务是相当有必要的;
- 作为应用管理人员,可以通过监控平台查看各个节点实例的运行状态,包括数据库连接信息、服务调用、逻辑流或者页面流的调用情况及执行时长;
- 作为开发人员,可以查看自己的节点实例在运行期的所有信息,Spring bean是否正常加载、yml配置是否起效,如何修改等;
- 作为运维人员,可以通过平台查看各个服务节点的日志,而不用从分散各地的服务器拉取日志,查看系统CPU、内存、堆栈等信息
监控策略-how
如何监控微服务呢?主要基于四种手段来监控:
-
Actuator
-
JMX
-
Spring admin
-
Swagger
-
actuator
-
admin
-
hystrix dashboard
-
分布式调用链
Spring Boot Actuator
简介
Spring Boot Actuator,即maven依赖为spring-boot-starter-actuator的模块,是Spring Boot的提供的众多Starter之一。是一个用于暴露自身信息的模块,其主要作用是用于监控与管理。
spring-boot-starter-actuator模块的实现对于实施微服务的中小团队来说,可以有效地减少监控系统在采集应用指标时的开发量。当然,它也并不是万能的,有时候也需要对其做一些简单的扩展,以实现自身系统个性化的监控需求。
入门使用
在已有的Spring boot应用中添加依赖:spring-boot-starter-actuator和spring-boot-starter-security,具体来说,在pom.xml文件添加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
即可在默认的服务以及端口查看监控信息,比如:http://localhost:8080/health, 会得到一串JSON字符串,表征当前系统的监控状况。加入security是为了保证actuator暴露的监控接口的安全性,访问应用监控端点时,都需要输入验证信息。本地的测试demo应用,Security依赖可以选择不加,即不需要引入安全管理,但生产环境不能这么做。
常用端点
Spring boot actuator自带很多默认的endpoint,如下:
端点 | 描述 | HTTP方法 |
---|---|---|
autoconfig | 显示自动配置的信息 | GET |
beans | 显示应用程序上下文所有的Spring bean | GET |
configprops | 显示所有@ConfigurationProperties的配置属性列表 | GET |
dump | 显示线程活动的快照 | GET |
env | 显示应用的环境变量 | GET |
env/{name} | 根据名称获取显示特定的环境变量 | GET |
health | 显示应用程序的健康指标,这些值由HealthIndicator的实现类提供。常见取值:UP DOWN UNKNOWN OUTOFSERVICE | GET |
info | 显示应用的信息,可使用 info.*属性自定义info端点公开的数据 | GET |
mappings | 显示所有的URL路径 | GET |
metrics | 显示应用的度量标准信息 | GET |
metrics/{name} | 根据指定的名称获取应用的度量标准信息 | GET |
shutdown | 关闭应用(默认情况下不启用,如需启用,需设置endpoints.shutdown.enabled=true) | POST |
trace | 提供HTTP请求跟踪信息(时间戳、HTTP头等,默认情况下为最近100个HTTP请求) | GET |
分类
Actuator监控分成两类:原生端点和用户自定义端点;自定义端点主要是指扩展性,用户可以根据自己的实际应用,定义一些比较关心的指标,在运行期进行监控。
上面的端点,根据端点的作用来说,可以原生端点分为三大类:
- 应用配置类:应用在运行期的静态信息,例如:自动配置信息、加载的spring bean信息、yml文件配置信息、环境信息、请求映射信息;
- 度量指标类:获取应用程序运行过程中用于监控的度量指标,比如:内存信息、线程池信息、HTTP请求统计、堆栈、请求连接数、健康指标、metrics信息等。
- 操作控制类:主要是指shutdown,提供对应用的关闭等操作类功能。
应用配置类
给出静态报告,因为这类应用配置端点所提供的信息报告在应用启动的时候都已经基本确定其返回内容。借助于这类端点,可以轻松获取一系列关于Spring 应用配置内容的详细报告,比如:自动化配置的报告、Bean创建的报告、环境属性的报告等。
/info
用来返回一些应用自定义的信息,以info开头的配置信息。默认情况下只返回一个空的json内容。在application.properties中通过info前缀来设置属性:
# 示例设置
info.app.name=spring-boot-actuator-silly-demo
info.app.version=v1.0.0
info.app.author=johnny
此后再访问/info端点,就不是默认的空的JSON字符串,而是包含上面自定义的信息。
/mappings
该端点用来返回所有Spring MVC的控制器映射关系报告。从下面的示例片段中,我们可以看该报告的信息与我们在启用Spring MVC的Web应用时输出的日志信息类似,其中bean属性标识了该映射关系的请求处理器,method属性标识了该映射关系的具体处理类和处理函数。
{
"/webjars/**": {
"bean": "resourceHandlerMapping"
},
"/**": {
"bean": "resourceHandlerMapping"
},
"/**/favicon.ico": {
"bean": "faviconHandlerMapping"
}
}
/autoconfig
该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项自动化配置的各个先决条件是否满足。所以,该端点可以帮助我们方便的找到一些自动化配置为什么没有生效的具体原因。该报告内容将自动化配置内容分为两部分:positiveMatches中返回的是条件匹配成功的自动化配置,negativeMatches中返回的是条件匹配不成功的自动化配置。
/beans
该端点用来获取应用上下文中创建的所有Bean。每个bean中都包含以下信息:
bean:Bean的名称
scope:Bean的作用域
type:Bean的Java类型
reource:class文件的具体路径
dependencies:依赖的Bean名称
/configprops
该端点用来获取应用中配置的属性信息报告。prefix代表属性的配置前缀,properties代表各个属性的名称和值。所以,我们可以通过该报告来看到各个属性的配置路径,比如我们要关闭该端点,就可以通过使用endpoints.configprops.enabled=false来完成设置。
/env
与/configprops不同(configprops关注于配置信息),/env关注运行环境信息,用来获取应用所有可用的环境属性报告。包括:环境变量、JVM属性、应用的配置配置、命令行中的参数,包括应用还没有没有使用的配置。可方便地看到当前应用可以加载的配置信息,并配合@ConfigurationProperties注解将它们引入到我们的应用程序中来进行使用。为了避免敏感信息暴露到 /env 里,所有名为password、secret、key(或者名字中最后一段是这些)的属性在 /env 里都会加上*。
度量指标类
给出动态报告,因为提供应用程序在运行过程中的一些快照信息,比如:内存使用情况、HTTP请求统计、外部资源指标等。
/metrics
最重要的监控端点,提供应用运行状态的完整度量指标报告,主要包括:内存信息、线程信息、垃圾回收信息、类加载信息等。对于生产级别的应用,数据量可能比较大。对于监控系统中的各项监控功能,它们的监控内容、数据收集频率都有所不同,如果每次都通过全量获取报告的方式来收集,略显粗暴。故而可以通过/metrics/{name}接口来获取细粒度的度量信息,比如通过访问/metrics/mem.free来获取当前可用内存数量。
返回JSON数据类似于(缩减版):
{
"counter.status.404.star-star": 2,
"nonheap.init": 2496,
"httpsessions.max": -1,
"httpsessions.active": 0
}
这些数据信息来自于包java.lang.management.*下面的接口的(方法)。httpsessions,Tomcat容器的会话使用情况,包括最大会话数httpsessions.max和活跃会话数httpsessions.active。该度量指标信息仅在引入了嵌入式Tomcat作为应用容器的时候才会提供。
对 /metrics接口提供的信息进行简单分类如下表:
分类 | 前缀 | 报告内容 |
---|---|---|
垃圾收集器 | gc.* | 已经发生过的垃圾收集次数,以及垃圾收集所耗费的时间,适用于标记-清理垃圾收集器和并行垃圾收集器,数据源自java.lang.management.GarbageCollectorMXBean(后面省略包名) |
内存 | mem.* | 分配给应用程序的内存数量和空闲的内存数量,数据源自Runtime |
堆 | heap.* | 当前内存用量,数据源自MemoryUsage |
类加载器 | classes.* | JVM类加载器加载与卸载的类的数量,数据源自ClassLoadingMXBean |
系统 | processors、instance.uptime、uptime、systemload.average | 系统信息,例如处理器数量数据源自Runtime、运行时间数据源自RuntimeMXBean、平均负载数据源自OperatingSystemMXBean |
线程池 | thread.* | 线程、守护线程的数量,以及JVM启动后的线程数量峰值,数据源自ThreadMXBean |
数据源 | datasource.* | 数据源连接的数量,源自数据源的元数据,仅当Spring应用程序上下文里存在 DataSource Bean 的时候才会有这个信息 |
Tomcat 会话 | httpsessions.* | Tomcat的活跃会话数和最大会话数,数据源自嵌入式Tomcat的Bean,仅在使用嵌入式Tomcat服务器运行应用程序时才有这个信息) |
HTTP | counter.status.、gauge.response. | 多种应用程序服务HTTP请求的度量值与计数器 |
一些度量值,比如数据源和Tomcat会话,仅在应用程序中运行特定组件时才有数据。你还可以注册自己的度量信息。
HTTP的计数器和度量值需要做一点说明。counter.status 后的值是HTTP状态码,随后是所请求的路径。举个例子,counter.status.200.metrics 表明/metrics端点返回 200(OK) 状态码的次数。
HTTP的度量信息在结构上也差不多,却在报告另一类信息。它们全部以gauge.response 开头,,表明这是HTTP响应的度量信息。前缀后是对应的路径。度量值是以毫秒为单位的时间,反映最近处理该路径请求的耗时。
root路径指向的是根路径或/。star-star代表那些Spring 认为是静态资源的路径,包括图片、js和css,其中还包含那些找不到的资源。这就是为什么你经常会看到 counter.status.404.star-star,这是返回404 (NOT FOUND)状态的请求数。
/metrics接口会返回所有的可用度量值,要获取单个值,请求时可以在URL后加上对应的键名。
/dump
生成当前线程活动的快照,方便在日常定位问题时查看线程的情况,主要展示线程名、线程ID、线程的状态、是否等待锁资源等信息。使用ThreadMXBean的dumpAllThreads方法来返回所有含有同步信息的活动线程详情。
/trace
该端点用来返回基本的HTTP跟踪信息,包括请求方法、路径、时间戳以及请求和响应的头信息,记录每一次请求的详细信息。默认情况下,跟踪信息的存储采用InMemoryTraceRepository实现的内存方式,始终保留最近的100条请求记录。
/health
用来获取应用的各类健康指标信息,包含磁盘检测和数据库检测。actuator模块中自带实现一些常用资源的健康指标检测器,通过实现HealthIndicator接口,并且会根据依赖关系的引入实现自动化装配,比如用于检测磁盘的DiskSpaceHealthIndicator、检测DataSource连接是否可用的DataSourceHealthIndicator等。
通过重写health()函数来实现健康检查,返回的Heath对象中,共有两项内容,一个是状态信息,除了该示例中的UP与DOWN之外,还有UNKNOWN和OUT_OF_SERVICE,可以根据需要来实现返回;还有一个详细信息,采用Map的方式存储,在这里通过withDetail函数,注入一个Error Code信息,我们也可以填入一下其他信息,比如,检测对象的IP地址、端口等。
增加自定义统计值。只需要通过注入CounterService和GaugeService来实现自定义的统计指标信息。比如:我们可以像下面这样自定义实现对hello接口的访问次数统计。
@RestController
public class HelloController {
@Autowired
private CounterService counterService;
@RequestMapping("/hello")
public String greet() {
counterService.increment("didispace.hello.count");
return "";
}
}
操作控制类
/shutdown
通过如下配置开启它:
endpoints.shutdown.enabled=true
实际上,由于之前介绍的所有端点都是用来反映应用自身的属性或是运行中的状态,相对于操作控制类端点没有那么敏感,所以他们默认都是启用的。而操作控制类端点拥有更强大的控制能力,如果要使用它们的话,需要通过属性来配置开启。
在原生端点中,只提供了一个用来关闭应用的端点:。
在配置了上述属性之后,只需要访问该应用的/shutdown端点就能实现关闭该应用的远程操作。由于开放关闭应用的操作本身是一件非常危险的事,所以真正在线上使用的时候,我们需要对其加入一定的保护机制,比如:定制Actuator的端点路径、整合Spring Security进行安全校验等。
进阶使用
对于敏感路径:
方法一:
management:
security:
enabled: false
方法二:
添加 spring-boot-starter-security;
并设置访问的密码,如果不设置,则是一个随机值,在启动时会打印。
security:
basic:
enabled: true
user:
name: johnny
password: awesome
自定义端点metrics
Spring Boot允许开发人员以编码的方式提供更丰富指标信息,通过/metrics端点来访问。counter是以Number类型来展现的指标;gauge是衡量双精度计算的指标。任何位置都可以注入CounterService或GaugeService。
counterService.increment(“metricName”);
counterService.decrement(“metricName”);
counterService.reset(“metricName”);
gaugeService.submit(“metricName”, 2.5);
敏感信息访问限制
根据上面表格,鉴权为false的,表示不敏感,可以随意访问,否则就是做了一些保护,不能随意访问。
endpoints.mappings.sensitive=false
这样需要对每一个都设置,比较麻烦。敏感方法默认是需要用户拥有ACTUATOR角色,因此,也可以设置关闭安全限制:
management.security.enabled=false
或者配合Spring Security做细粒度控制。
启用和禁用接口
默认情况下所有接口(除/shutdown)都启用。比如要禁用 /dump 接口,则可以设置如下:
endpoints.dump.enabled = false
如果只想打开一两个端口,可以先禁用全部端口,然后启用某几个:
endpoints.enabled = false
endpoints.metrics.enabled = true
重写健康检测
因为项目里面用到redis集群,但并不是用spring boot的配置方式,启动后项目健康检查老是检查redis的时候状态为down,导致注册到eureka后项目状态也是down。
"redis": {
"status": "DOWN",
"error": "org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool"
}
问下能不能设置spring boot不检查 redis的健康状态?
解决方法:
@Component("redisHealthIndicator")
public class MyRedisHealthIndicator implements HealthIndicator {
@Override
public Health health() {
return Health.up().build();
}
}
实现HealthIndicator
接口中的health方法,直接返回up状态。通过@Component
注解,让Spring Boot扫描到该类就能自动的进行加载,并覆盖原来的redis健康检查实现RedisHealthIndicator。
使用shell连接Actuator
Actuator可通过shell的方式连接,不过在Spring Boot 1.5后已被废弃。通过shell连接Actuator,需在工程的pom文件加上依赖spring-boot-starter-remote-shell,启动SB应用程序,在程序的控制台会输出连接shell的密码,密码是随机的,每次都不一样:
用户名是user,端口是2000,固定写死,连接命令:
ssh user@localhost -p 2000
输入启动应用时打印输出的随机密码,
连接上shell后,这时可以通过终端查看Actuator的各个端点。Spring Boot提供了4个特有的shell命令:
- beans:列出SB应用上下文的Bean
- endpoint:调用Actuator端口
- metrics:度量信息
- autoconfig:生成自动配置说明报告
Hystrix dashboard
使用Hystrix Dashboard展示Hystrix用于熔断的各项度量指标,可以方便的查看服务实例的综合情况,比如:服务调用次数、服务调用延迟等;但是只能实现对单个服务实例的数据展现。多实例情况下,可以使用Turbine将这些度量指标数据进行聚合。
Spring Cloud构建微服务架构:Hystrix监控面板【Dalston版】
Spring Cloud构建微服务架构:Hystrix监控数据聚合【Dalston版】
分布式调用链
推荐资料:
Spring Boot Actuator监控端点小结
使用 spring-boot-admin 对 Spring Boot 服务进行监控
学习视频