Springboot Actuator之五:Springboot中的HealthAggregator、新增自定义Status
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_WARNINGpublic 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,依次类推。