
club.zhcs.lina.starter.monitor.health.ChainHealthIndicator Maven / Gradle / Ivy
package club.zhcs.lina.starter.monitor.health;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.nutz.lang.Lang;
import org.nutz.lang.Stopwatch;
import org.nutz.lang.Tasks;
import org.nutz.lang.Times;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.Status;
import club.zhcs.lina.starter.monitor.MonitorConfigurationProperties.Chain.Service;
import club.zhcs.lina.starter.monitor.health.HealthChecker.ServiceHealth;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
/**
*
* @author Kerbores([email protected])
*
*/
@RequiredArgsConstructor
public class ChainHealthIndicator implements HealthIndicator {
private final List services;
private final long interval;
private final HealthChecker healthChecker;
List healths;
Log logger = Logs.get();
@PostConstruct
public void init() {
// 定时检查链路可用性
Tasks.scheduleAtFixedRate(this::healthCheckTask, Times.now(), this.interval, TimeUnit.SECONDS);
}
/**
* 执行健康检查
*/
public void healthCheckTask() {
try {
CountDownLatch countDownLatch = new CountDownLatch(this.services.size());
this.healths = Lang.list();
Stopwatch watch = Stopwatch.begin();
this.logger.debugf("执行健康检测开始: %s", Times.format("yyyy-MM-dd HH:mm:ss", Times.now()));
if (Lang.isNotEmpty(this.services)) {
this.services.stream()
.forEach(service -> new Thread(() -> this.healths.add(this.checkService(service))).start());
}
countDownLatch.await();
watch.stop();
this.logger.debugf("执行健康检测结束: %s 耗时 %d 毫秒", Times.format("yyyy-MM-dd HH:mm:ss", Times.now()), watch.du());
}
catch (InterruptedException e) {
this.logger.error(e);
Thread.currentThread().interrupt();
}
}
/**
* 单个接口的监控检查
*
* @param service
* @return
*/
private ServiceHealth checkService(Service service) {
return this.healthChecker.check(service);
}
@Override
public Health health() {
while (!this.services.isEmpty() && this.healths.isEmpty()) {// 如果检测的时候正好在跑且正好情况,那么稍等一下
try {
Thread.sleep(20);// 20ms
}
catch (InterruptedException e) {
this.logger.error(e);
Thread.currentThread().interrupt();
}
}
org.springframework.boot.actuate.health.Health.Builder builder = Health
.status(this.healths.stream()
.allMatch(h -> h.getStatus() == Status.UP) ? Status.UP
: Status.DOWN);
this.healths.stream()
.forEach(h -> builder.withDetail(h.getService(),
NutMap.NEW().addv("status", h.getStatus().getCode()).addv("time", h.getTime())));
return builder.build();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy