springboot的actuator内置了/health的endpoint,很方便地规范了每个服务的健康状况的api,而且HealthIndicator可以自己去扩展,增加相关依赖服务的健康状态,非常灵活方便而且可扩展。

/health实例

{
"status": "UP",
"custom": {
"status": "UNKNOWN",
"custom": {
"status": "UNKNOWN",
"msg": "mock down to test aggregator"
}
},
"diskSpace": {
"status": "UP",
"total": 249779191808,
"free": 57925111808,
"threshold": 10485760
}
}

health的Status枚举

org.springframework.boot.actuate.health.Status.java

@JsonInclude(Include.NON_EMPTY)
public final class Status { /**
* {@link Status} indicating that the component or subsystem is in an unknown state.
*/
public static final Status UNKNOWN = new Status("UNKNOWN"); /**
* {@link Status} indicating that the component or subsystem is functioning as
* expected.
*/
public static final Status UP = new Status("UP"); /**
* {@link Status} indicating that the component or subsystem has suffered an
* unexpected failure.
*/
public static final Status DOWN = new Status("DOWN"); /**
* {@link Status} indicating that the component or subsystem has been taken out of
* service and should not be used.
*/
public static final Status OUT_OF_SERVICE = new Status("OUT_OF_SERVICE");

对多个Status的聚合

对于多个HealthIndicator的status,spring boot默认对其进行aggregrate,然后计算最顶层的status字段的值,而且对于status是DOWN或者是OUT_OF_SERVICE的,返回的http的状态码是503,这对于应用监控系统来说真是大大的贴心啊,再总结一下:

  • 自动聚合多个HealthIndicator的status
  • 对于status是DOWN或者是OUT_OF_SERVICE的,返回503

这样应用监控系统一来就无需去解析返回结果,直接根据http的状态码就可以判断了,非常方便,太省心了有没有。

看看AbstractHealthAggregator.java的抽象类,其中对状态的聚合是abstract的。

public abstract class AbstractHealthAggregator implements HealthAggregator {

    @Override
public final Health aggregate(Map<String, Health> healths) {
List<Status> statusCandidates = new ArrayList<Status>();
for (Map.Entry<String, Health> entry : healths.entrySet()) {
statusCandidates.add(entry.getValue().getStatus());
}
Status status = aggregateStatus(statusCandidates);
Map<String, Object> details = aggregateDetails(healths);
return new Health.Builder(status, details).build();
} /**
* Return the single 'aggregate' status that should be used from the specified
* candidates.
* @param candidates the candidates
* @return a single status
*/
protected abstract Status aggregateStatus(List<Status> candidates); /**
* Return the map of 'aggregate' details that should be used from the specified
* healths.
* @param healths the health instances to aggregate
* @return a map of details
* @since 1.3.1
*/
protected Map<String, Object> aggregateDetails(Map<String, Health> healths) {
return new LinkedHashMap<String, Object>(healths);
} }

自定义Status,以及对Status聚合逻辑的调整

重写参考了OrderedHealthAggregator类,增加了 GIT_WARNING

public class OrderedHealthAggregator extends AbstractHealthAggregator {

    private List<String> statusOrder;

    public static final Status GIT_WARNING = new Status("GIT_WARNING", "警告:config-server连不上gitlab,请及时处理.");

    /**
* Create a new {@link OrderedHealthAggregator} instance.
*/
public OrderedHealthAggregator() {
setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, GIT_WARNING, Status.UP, Status.UNKNOWN);
} /**
* Set the ordering of the status.
* @param statusOrder an ordered list of the status
*/
public void setStatusOrder(Status... statusOrder) {
String[] order = new String[statusOrder.length];
for (int i = 0; i < statusOrder.length; i++) {
order[i] = statusOrder[i].getCode();
}
setStatusOrder(Arrays.asList(order));
} /**
* Set the ordering of the status.
* @param statusOrder an ordered list of the status codes
*/
public void setStatusOrder(List<String> statusOrder) {
Assert.notNull(statusOrder, "StatusOrder must not be null");
this.statusOrder = statusOrder;
} @Override
protected Status aggregateStatus(List<Status> candidates) {
// Only sort those status instances that we know about
List<Status> filteredCandidates = new ArrayList<Status>();
for (Status candidate : candidates) {
//只识别Status.DOWN, Status.OUT_OF_SERVICE, GIT_WARNING, Status.UP, Status.UNKNOWN几种状态
if (this.statusOrder.contains(candidate.getCode())) {
filteredCandidates.add(candidate);
}
}
// If no status is given return UNKNOWN
if (filteredCandidates.isEmpty()) {
return Status.UNKNOWN;
}
//对多个结果状态的排序,按照各个状态在statusOrder集合中的位置排序
Collections.sort(filteredCandidates, new StatusComparator(this.statusOrder)); //返回排在最上面的那个状态值
return filteredCandidates.get(0);
} /**
* {@link Comparator} used to order {@link Status}.
*/
private class StatusComparator implements Comparator<Status> { private final List<String> statusOrder; StatusComparator(List<String> statusOrder) {
this.statusOrder = statusOrder;
} @Override
public int compare(Status s1, Status s2) {
//对多个结果状态的排序,按照各个状态在statusOrder集合中的位置排序
int i1 = this.statusOrder.indexOf(s1.getCode());
int i2 = this.statusOrder.indexOf(s2.getCode());
return (i1 < i2 ? -1 : (i1 == i2 ? s1.getCode().compareTo(s2.getCode()) : 1));
} } }

即Status.DOWN, Status.OUT_OF_SERVICE, GIT_WARNING, Status.UP, Status.UNKNOWN优先级依次递减。status中一旦有出现DOWN的情况,整体的status就是DOWN,依次类推。

Springboot Actuator之五:Springboot中的HealthAggregator、新增自定义Status的更多相关文章

  1. Winform中实现ZedGraph新增自定义Y轴上下限、颜色、标题功能

    场景 Winform中实现ZedGraph的多条Y轴(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1001322 ...

  2. 5. SpringBoot —— Actuator简介

    Actuator是SpringBoot提供的用来帮助我们在将应用程序推向生产环境时对其进行监视和管理的工具集.使用Actuator最简单的方式,就是在pom文件中添加如下依赖: <depende ...

  3. SpringBoot actuator 应用监控。

    前言 : 今天在阅读 <SpringCloud微服务实战>一书时看到了SpringBoot actuator相关知识,并且自己也本地调试实践.觉得SpringBoot这一套监控还是挺有意思 ...

  4. springboot Actuator健康检查

    通过情况下,如我们想在系统中添加一个健康检查的接口,我们怎么做呢? 我们会新建一个类,或在已存在类的基础上添加检测接口. package com.crhms.medicareopinion; impo ...

  5. SpringBoot Actuator & SpringBoot Admin

    SpringBoot Actuator提供了很多监控和管理你的spring boot应用的HTTP或者JMX端点,并且你可以有选择地开启和关闭部分功能. 当你的spring boot应用中引入依赖之后 ...

  6. Springboot Actuator之八:actuator的执行原理

    本文接着<Springboot Actuator之七:actuator 中原生endpoint源码解析1>,前面主要分析了原生endpoint的作用. 现在着重了解actuator的执行原 ...

  7. SpringBoot Actuator监控【转】

    springboot actuator 监控 springboot1.5和springboot2.0 的actuator在启动日志上的差异就很大了. springboot1.5在启动时会打印很多/XX ...

  8. springboot actuator 配置安全

    springboot actuator监控是什么?类似php的phpinfor()函数,不过actuator更强大,可以查看的数据.状态更多.Actuator是Spring Boot提供的对应用系统的 ...

  9. SpringBoot Actuator — 埋点和监控

    项目中看到了有埋点监控.报表.日志分析,有点兴趣想慢慢捣鼓一下 1. 数据埋点 监控机器环境的性能和业务流程或逻辑等各项数据,并根据这些数据生成对应的指标,那么我们就称为数据埋点.比如我们想知道某个接 ...

随机推荐

  1. 不要在 MySQL 中使用“utf8”,请使用“utf8mb4”

    不要在 MySQL 中使用“utf8”,请使用“utf8mb4” 最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后出现了一个离奇的错误: ...

  2. js对象常用属性和方法:复制一个对象,获取一个对象的所有key和所有value的方法

    记录对象的一些实用使用方法及属性 // Object.assign() 多个对象合并 key相同则后面的覆盖前面的 const target = { a: 1, b: 2 }; const sourc ...

  3. UUID生成库libuuid和crossguid

    libuuid是一个开源的用于生成UUID(Universally Unique Identifier,通用唯一标识符)的库. 可从https://sourceforge.net/projects/l ...

  4. SAP里SE38设置模板

    经验丰富些的大佬们都会有一套自己的风格,比如report主程序里几个form,常见的fieldcat的宏定义,常见的一些数据定义等等. 1.使用事物代码SE38进入编辑器. 2.点击客户端最右下角的文 ...

  5. 【前端_js】jQuery动态设置元素的样式

    1.用css()方法查询元素的某个样式 $("div").css("padding-left")); 2.用css()方法设置元素的样式 法一: $(" ...

  6. JMETER 生成测试报告

    JMETER测试报告样例 JMETER 提供的生成测试报告功能,能够生成漂亮的HTML测试报告. 上图是测试统计图 20个用户并发,测试时长一分钟,发起流程320次,没有出错,TPS为6.5,平均发起 ...

  7. Java八大排序之基数排序

    基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分 ...

  8. 使用 python set 去重 速度到底是多快呢???

    这次去测试一下 python 的set去重,速度怎么样? 我们要做的是把文件一次性读取到内存中,然后去重,输出去重的长度. 第一步:对 121w 条数据去重,看去重话费的时间 上证据: 第二步:对 1 ...

  9. Mock.js数据模拟

    数据来源方式: 为什么要用mockjs 实际开发中,前后端分离,前端需要后端的接口去完成页面的渲染,但是并不能等到后端成员写完接口再开始进行测试.大部分情况下,前后端需要同时进行开发.因此便需要moc ...

  10. flask实战-个人博客-编写博客前台

    编写博客前台 博客前台需要开放给所有用户,这里包括显示文章列表.博客信息.文章内容和评论等功能功能. 分页显示文章列表 为了在主页显示文章列表,我们要先在渲染主页模板的index视图的数据库中获取所有 ...