【问题标题】:Add Spring Actuator's healthcheck without Boot and @EnableAutoConfiguration在没有 Boot 和 @EnableAutoConfiguration 的情况下添加 Spring Actuator 的健康检查
【发布时间】:2016-10-26 09:45:55
【问题描述】:

我想将 Actuator 添加到我的 Spring 应用程序(不是 Spring Boot)。 准确地说,我需要使用执行器 HealthCheck,这样我就可以创建不同健康指标的 bean,它们会在 /health 上创建完整的健康检查。

起初我尝试将@EndpointAutoConfiguration 添加到我的@Configuration 类中,但存在bean 冲突,因为我有我真正需要的自定义bean,因此在HealthIndicatorAutoConfiguration 之外的其他配置中不需要/p>

【问题讨论】:

  • 嘿,你得到这个问题的答案了吗?我现在有同样的问题,我不想使用 @EnableAutoConfiguration@SpringBootApplication 但想使用执行器。
  • @Sujan 不是真的,我已经创建了自定义 HealthIndicator 和 HealthIndicatorCollector。在 /healthcheck 请求 HealthcheckCollector 从上下文中获取所有 HealthIdicator bean 并向我提供它们的状态。因此,我为每个 HeathIndicator 添加了“关键”字段,因此 HeathCollector 可以为我提供服务的运行状况,而忽略不重要但可能对监控有用的指标。​​
  • @ottercoder 您能否与我们分享您在此处使用的自定义代码。
  • @BandhamManikanta 发现了一些 2016 年的代码:D

标签: java spring spring-mvc spring-boot-actuator


【解决方案1】:

可能的解决方案是创建具有关键字段的自定义 HealthIndicator 和 HealthIndicatorCollector。还要添加一个 servlet:

contextHandler.addServlet(new ServletHolder(platformHealthCheckServlet), "/healthcheck");

从上下文中收集所有自定义 HealthIndicators 并在 /healthcheck 端点创建漂亮的状态 json:

@Autowired
public CustomHealthCheckServlet(Map<String, CustomHealthIndicator> healthIndicatorMap, ObjectMapper objectMapper) {
    this.healthIndicatorMap = Collections.unmodifiableMap(healthIndicatorMap);
    this.mapper = objectMapper;
}

CustomHealthIndicator,增加了setCritical方法:

public interface CustomHealthIndicator extends HealthIndicator {
    void setCritical(boolean var1);
}

CustomAbstractHealthIndicator 覆盖 AbstractHealthIndicator 中的 doHealthCheck 方法,为其构建器添加关键细节并创建自己的抽象方法 doCheck

public abstract class CustomAbstractHealthIndicator extends AbstractHealthIndicator 
implements CustomHealthIndicator {
    private boolean critical = false;

    public CustomAbstractHealthIndicator() {
     }

    public void setCritical(boolean critical) {
        this.critical = critical;
    }

    @Override
    protected void doHealthCheck(Builder builder) throws Exception {
        builder.withDetail("critical", this.critical);
        this.doCheck(builder);
    }

    protected abstract Builder doCheck(Builder var1) throws Exception;
}

还有另一个自定义类聚合健康 bean 并根据每个健康的关键状态计算整个应用程序的状态,忽略不重要但可能对监控有用的指标:

public class CustomHealthAggregator implements HealthAggregator {

    private List<String> statusOrder;

    public CustomHealthAggregator() {
        setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, Status.UP, 
Status.UNKNOWN);
    }

    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));
    }

    public void setStatusOrder(List<String> statusOrder) {
        Assert.notNull(statusOrder, "StatusOrder must not be null");
        this.statusOrder = statusOrder;
    }

    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) {
            if (this.statusOrder.contains(candidate.getCode())) {
                filteredCandidates.add(candidate);
            }
        }
        // If no status is given return UP
        if (filteredCandidates.isEmpty()) {
            return Status.UP;
        }
        // Sort given Status instances by configured order
        Collections.sort(filteredCandidates, 
        new StatusComparator(this.statusOrder));
        return filteredCandidates.get(0);
    }

    @Override
    public Health aggregate(Map<String, Health> healths) {
        List<Status> statusCandidates = healths.entrySet()
                .stream()
                .filter(healthEntry -> 
              healthEntry.getValue().getDetails().get("critical").equals(true))
                .map(e -> e.getValue().getStatus())
                .collect(Collectors.toList());

        Status status = aggregateStatus(statusCandidates);
        Map<String, Object> details = new LinkedMap();
        details.put("version", AppVersionUtil.getAppVersion());
        details.putAll(aggregateDetails(healths));
        return new Health.Builder(status, details).build();
    }

    protected Map<String, Object> aggregateDetails(Map<String, Health> healths) 
    {
        return new LinkedHashMap<String, Object>(healths);
    }

    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) {
            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));
        }

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2016-01-27
    相关资源
    最近更新 更多