Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Spring Boot /actuator/heath run checks in parallel

I have several custom checks for my /actuator/health check. Some of these call other services to see if they are reachable. Unfortunately this can take some time. Therefore I'd like spring boot to make these checks in parallel.

Demo:

@Component
public class HealthCheck1 extends AbstractHealthIndicator {
    @Override
    protected void doHealthCheck(Health.Builder builder) throws InterruptedException {
        Thread.sleep(5000); // actually make a service call
        builder.up();
    }
}

@Component
public class HealthCheck2 extends AbstractHealthIndicator {
    @Override
    protected void doHealthCheck(Health.Builder builder) throws InterruptedException {
        Thread.sleep(5000); // actually make a service call
        builder.up();
    }
}
$ time http localhost:8080/actuator/health
HTTP/1.1 200 
Connection: keep-alive
Content-Type: application/vnd.spring-boot.actuator.v3+json
Date: Fri, 03 Jan 2020 14:54:31 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked

{
    "components": {
        "diskSpace": {
            "details": {
                "free": 398020632576,
                "threshold": 10485760,
                "total": 499963174912
            },
            "status": "UP"
        },
        "healthCheck1": {
            "status": "UP"
        },
        "healthCheck2": {
            "status": "UP"
        },
        "ping": {
            "status": "UP"
        }
    },
    "status": "UP"
}


real    0m10.359s
user    0m0.242s
sys 0m0.036s

This shows that the checks are currently made sequentially. Is there a way to change that?

like image 910
R2C2 Avatar asked Mar 14 '26 18:03

R2C2


1 Answers

Since currently its not really possible to run all health checks in parallel as @Roland Weisleder has pointed in comments, you can do the following workaround:

Instead of doing the actual check in HealthCheck1:

  1. create another bean that makes the long check
  2. Run it in some thread periodically (with @Scheduled, Scheduled Executor or whatever)
  3. Make it store a decision locally in a field, there is no multi-threaded access here, that bean is a singleton so you should be good to go.
  4. Inject that bean into the HealthCheck and get the state.
@Component
public class MyCustomBeanCheck {
   private boolean isOk;

   // run periodically
   public void doCheck() {
       isOk = contactServiceTakesALongTime();
   }

   public boolean isOk() {
      return isOk;
   }
}

public class HealthCheck1 extends AbstractHealthIndicator {

    private MyCustomBeanCheck myCustomBeanCheck;

    protected void doHealthCheck(Health.Builder builder) throws InterruptedException {
       if(myCustomBeanCheck.isOk()) { // immediate access
         builder.up();
       } else {
         builder.down();
       }
    }
}
like image 82
Mark Bramnik Avatar answered Mar 17 '26 07:03

Mark Bramnik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!